C# 例外処理① try catch

こんにちは。レモンティーです。

今回はC#の例外処理についてです。

「例外」というのはざっくり言うとエラーです。

例えばAndroidアプリのテストプレイ中に
0で割り算したり、配列のインデックスオーバーを起こしたりすると
「問題が発生したため、アプリを終了します」
と表示されてアプリを終了してしまいます。

まさにこれが「例外が発生している」状況です。
例外処理とはこれに対処することです。

try-catch

例外処理の一番基本的な書き方は↓のようになります。

try{

     //普通の処理。ここで例外が発生すると検出される

}catch{

 //↑で例外が発生した場合のみ実行される処理。例外への対処など。

}

tryブロック内に書かれた処理の途中で例外が発生すると
処理が中断され、catchブロックに移ります。
例外が発生しなければcatchブロックは実行されません。


例えばこんな感じです

try{

int n = 100;
string s = Console.ReadLine();
int m = int.Parse(s);
int a = n/m;
Console.WriteLine(a);

}catch{

Console.WriteLine("例外発生");

}

Console.ReadLine();

100を入力した数値で割るだけですが、入力によっては例外が発生します。
数値以外が入力された場合や、0が入力された場合です。
そのような場合、処理はcatchブロックに移り、出力は
「例外発生」となります。

それ以外ではcatchブロックは実行されず、普通に計算結果が出力されます。
2と入力したら出力は「50」です。

例外の種類ごとに処理を分ける

例外の検出はできましたが、どんな例外にも「例外発生」と表示されると
どの例外が発生したのかわかりません。
例外を区別できたら便利です。

そのためには、↓のように
例外をキャッチする際に例外のクラスを指定します。

try{

}catch(例外のクラス){
  //指定されたクラスとその派生クラスの例外にのみ反応
}

「0で割った」などの標準的な例外は
System.Exceptionから派生するクラスとして
あらかじめ定義されています。

たとえば「0で割った」は
System.DivideByZeroException です。


それでは例外の区別を実際にやってみます。

try{

int n = 100;
string s = Console.ReadLine();
int m = int.Parse(s);
int a = n/m;
Console.WriteLine(a);

}catch(System.DivideByZeroException){

Console.WriteLine("例外が発生しました。0以外を入力してください");

}catch{

Console.WriteLine("何らかの例外が発生しました");

}

Console.ReadLine();

これでcatchブロックを増やせば
例外ごとに違った適切な対処が可能ですね。

注意点としては、catchブロックは上から順に処理されることです。

そのため、もしもこのプログラムで
二つのcatchブロックの順番を入れ替えた場合、
全ての例外処理がなにも指定していないcatchブロックで行われるため
catch(System.DivideByZeroException)が実行されることは
あり得なくなってしまいます。なら書く意味ないですね。
これはコンパイルエラーになります。
何も指定しないcatchブロックは一番下に書かなければいけません。

同じ理由で、継承関係がある例外を別々に指定する場合も
親クラスのcatchブロックを下側に書かなくてはいけません。

例外の詳細を知る

例外のより詳しい情報を得るには↓のようにします

try{

}catch(System.Exception e){

                Console.WriteLine(e.Message);
                Console.Write(e.TargetSite);
                Console.WriteLine(e.StackTrace);
}

eはcatchブロック内でのみ有効な変数です。
↑のようにこれを介して例外の様々な情報にアクセスできます

Messageは例外の説明。TargetSiteは例外が発生したメソッド。
StackTraceは例外が投げられた時のメソッドよびだしのトレースです。

この場合
Messageは「0 で除算しようとしました。」となります。

コンソールアプリのMainメソッドに書いたため
TargetSiteは「Void Main(System.String[]) 」となりました。

StackTraceは長いので省きます。



これでtry-catchでいろいろな処理ができますね。
今回はこれでおしまいです。

sawalemounity.hatenablog.com