はなちるのマイノート

Unityをメインとした技術ブログ。自分らしくまったりやっていきたいと思いますー!

【C#】例外処理を今更ながらまとめてみる

はじめに

C#のプログラミングを初めて3年ぐらい経ちますが、いまだに上手に例外処理を使えていない有様だったのでこれを機にまとめてみようと思いました。

基本的な文法からExceptionの自作派生クラスを作るまでを一通りやっていきます。

基本文法

まずは例外を検知する側の基本文法を一気にみていきます。

登場するキーワードはtry,catch,finallyです。

static void Main(string[] args)
{
    int[] nums = new int[4];

    try
    {
        // エラーを検知したいコード
        nums[5] = 1;
    }
    catch (IndexOutOfRangeException e)
    {
        // もし配列の添字の限界を超えた場合、tryでの処理を中止してこのブロック内のコードが実行される
        Console.WriteLine($"[{e.GetType().Name}] {e.Message}");
        Console.WriteLine(e.StackTrace);
    }
    catch (DivideByZeroException)
    {
        // 例外オブジェクト名を指定しなくてもOK
        Console.WriteLine("Cant't divide by Zero!");
    }
    catch
    {
        // すべての例外がここで補足される
        // 前に対応したブロック(ex. IndexOutOfRangeException)があればこのブロックは実行されない
        Console.WriteLine("Some exception occurred.");
    }
    finally
    {
        // 最後に実行するコード
        // メソッドを中止してもエラーがなくともこのブロックのコードは実行される
        Console.WriteLine("Leaving try.");
    }
}

例外を投げる側

検知する側は先程紹介したので、今度は例外を投げる方を実装してみましょう。

使うキーワードはthrowを使います。

public double Divide(int a, int b)
{
    // 例外を投げると処理が中断される
    if (b == 0) throw new ArgumentException("bには0以外の値を指定してください");

    return a / b;
}

Exception

先程からなにげなく使っていますが、例外を扱うSystem.Exceptionクラスについて説明しておきたいと思います。
docs.microsoft.com

catch,throwキーワードで扱っていたクラスはすべてSystem.Exceptionクラスの派生クラスです。

ExceptionクラスのプロパティでMessage,StackTraceは超重要だと思うので覚えておくと良いと思います。

  • Message : 現在の例外を説明するメッセージを取得します。
  • StackTrace : 呼び出し履歴で直前のフレームの文字列形式を取得します。
catch(IndexOutOfRangeException e)
{
    // もし配列の添字の限界を超えた場合、tryでの処理を中止してこのブロック内のコードが実行される
    Console.WriteLine($"[{e.GetType().Name}] {e.Message}");
    Console.WriteLine(e.StackTrace);
}

またよく使うExceptionの派生クラスはArgumentNullException,ArgumentOutOfRangeException,ArgumentExceptionあたりでしょうか。

使いそうな派生クラスの一覧をまとめてくれている方がいらっしゃたので、貼っておきます。
qiita.com

あと公式ドキュメントにも一覧があります。
Exception クラス (System) | Microsoft Docs

自作Exceptionクラスを作る

自作例外を作ってより理解を深めてみましょう。

実装の仕方はシンプルでExcpetionクラスを継承すれば良いだけです。

class Program
{
    static void Main(string[] args)
    {
        try
        {
            throw new MyException();
        }
        catch(MyException e)
        {
            Console.WriteLine($"[{e.GetType().Name}] {e.Message}");
            Console.WriteLine(e.StackTrace);
        }
    }
}

public class MyException : Exception
{
    // 継承元のコンストラクタを呼ぶ
    public MyException() : base() { }

    public override string ToString()
    {
        return Message;
    }
}

注意したいこと

実際にこれらを使ってプロジェクトを作成するにあたって、気を付けたいことがいくつかあります。

基本文法だけ知っていてもこういったことは身につかないので一度目を通しておくと良いと思います。
qiita.com

さいごに

ざっと例外処理をまとめてみました。

あとは実践あるのみなので、積極的に使っていきたいと思います。

ではまた。