paizaで学んだC#の例外処理に関するまとめ

paizaで学んだC#の例外処理に関するまとめ

802 回閲覧されました

みなさんこんにちは、jonioです。

今回はpaizaでC#の例外処理を勉強した内容のまとめになります。

 

例外処理とは

プログラムに問題があった時の処理方法ですがどこで例外処理をするかはC#の実行手順を知っておかないといけませんが下記になります。

  1. ソースコードの記述
  2. コンピューターが実行できる形式に変換するコンパイル
  3. 計算や処理を行う実行

2のコンパイルエラーはコードの綴り間違いや文法間違いで起きて3の実行エラーは計算ができなかったりファイルがないなどの場合に起きますが3の実行時のエラーが例外処理の対象になります。

 

例外が発生する例

例外が発生するのは例えば↓の場合があります。

  • 0で割り算
  • 数値変換で数値ではない文字を指定
  • 配列の範囲外にアクセス
  • ファイルが存在しない

実行時のエラーがあった場合に例外処理をしないとプログラムが止まったりパソコンが対処してくれますがプログラムが使いにくくなるのでそうならない為に例外処理は存在します。

また例外処理が発生したらその部分のプログラムが動く事でエラーの部分を探しやすくなりエラーの原因も調べやすくなります。

 

簡単な例外処理の例

↓のコードで考えます。

これはエラーになります。

理由は 10行目のnumberは9行目で0と設定しているからです。

出力結果は「こんにちは」と表示されるので「こんにちは」の下のコードの9行目〜12行目の部分でエラーが起きている事が分かります。

ここから例外処理のコードに変えます。

例外が起きている(起きそうな)9行目〜12行目を↓の様に「try{}」の中に入れます。

そしてその場合にどう処理するかのコードをtry{ }の下に書きます。

10行目〜13行目のエラーの内容を15行目の「e」に代入して17行目の「e.Message」でエラーの内容を取得します。

今回の出力結果は「こんにちは Attempted to divide by zero. こんにちはC#」ですが「Attempted to divide by zero.」がエラーの内容になります。

この様に例外処理をするとエラーが出た場合にプログラムが止まらず例外の場合の処理がされてプログラムが最後まで実行されます。

ちなみに15行目〜18行目のcatchのブロックの部分を例外ハンドラと言います。

また例外が起きても起きなくても絶対に実行したい内容がある場合はコードを↓にします。

 

例外処理のエラーメッセージを分かりやすくする

コードを↓にします。

これでエラーの部分(13行目)のエラーメッセージは「System.DivideByZeroException: Attempted to divide by zero.at Example.Main () [0x0000e] in /workspace/Main.cs:13 」と表示されます。

17行目のWriteLineの前に「Error.」を付けると標準入力のエラーの出力タブに詳細なエラーメッセージが表示されてエラーの内容は出力されません。

 

複数の例外に対応させる

例外が出る場合は0で割るとかint.Parseで文字を数値に変換する時に「”1″」などを変換するのではなく「”a”」などを数値に変換する場合に起きますが複数の例外に対応できる様にします。

コードを↓にします。

今まではcatchのブロックが1つだけでしたが場合に合わせて複数記述する事もできます。

catchの「( )」の中身ですがExceptionが基底クラスでDivideByZeroExceptionやFormatExceptionは派生クラスにないるのでExceptionで派生クラスの例外を受け取る事ができます。

だからcatchを複数書く場合は↓の様に「catch(Exception)」を最後に書かないとコンパイルエラーになります。

規定クラスは25行目〜29行目です。

ちなみに「catch(Exception)」を最初に書いた場合は↓のエラーが表示されます。

 

throw

throwを使うと例外が発生しない状況でも例外を発生させる事ができます。

まず↓のコードで考えます。

このコードに意図的に例外が発生する為のコードを追加します。

14行目を追加していますが意図的に例外を発生させる場合のコードは「throw new 例外のパターン();」でこの場合の例外のパターンは「DivideByZeroException」で16行目の「catch (DivideByZeroException e)」のDivideByZeroExceptionと同じにしないとエラーになります。

これで出力は「Hello World 50 0では割り算できません Hello C#」になりエラーの出力では↓になります。

throwで引数を使う場合はコードを↓にします。

するとエラーの出力で↓になり「強制エラー」が追加されているのが確認できます。

 

例外は呼び出し元に戻る

↓のコードで考えます。

8行目の引数が0なので16行目でエラーになります。

エラーの出力は↓になります。

18行目のreturnを使ったメソッドの場合に例外はどこに行ってるかですが呼び出し元の8行目の「Test(0);」に渡っています。

そこで例外が起きているコードをtry{ }の中に入れたコードに変えてcatch{ }でエラーを出力させます。

これで「1 2 4 エラーメッセージ」が出力されます。

次にメソッド側でも例外を起こしてメソッドの呼び出し元に伝えてみます。

コードを↓にします。

これで「1 2 3 5 8 エラーメッセージ」の順に表示されます。

コードの流れを解説します。

まず7行目で「1」を出力します。

次に11行目で22行目〜43行目のTestメソッドを呼び出しますが24行目で「2」を出力して28行目で「3」を出力しますが11行目の引数が0なので計算不能で30行目が実行されず37行目の5 が出力されます。

そして38行目の「throw」で15行目に戻って17行目から「8」を出力して18行目からエラーメッセージを出力します。

38行目のthrowですがcatchの中で例外を15行目に投げていてこのthrowの事を例外の再throwと言います。