こんにちは。倉内です。
最近はWebブラウザ上でプログラミング学習ができるサービスも増え、ITエンジニアを目指している方はもちろん、業務の効率化や趣味でちょっと使ってみたいという方でも手軽に学習を始められるようになりました。
たとえば、paizaラーニングではプログラミングの基礎を学べる「言語入門講座」を終えて、「そろそろ何か作ってみたい…」という方向けに「Webアプリ開発入門講座」をご用意しています。
Webアプリケーション開発には機能の実装はもちろん重要ですが、プログラムの安定性やセキュリティについても考えられるようになるとよりよいですね。
そこで今回は、C#でのプログラムの例外処理について解説したいと思います。例外処理は実務を経験するとその重要性を実感すると思いますが、プログラミング学習を始めたばかりの方にとっては少し難しいかもしれません。具体例などを挙げて説明していきますので一緒に学んでいきましょう。
なお、paizaラーニングには、C#の他にJava・PHP・Ruby・Pythonの言語入門講座に例外処理のレッスンがありますのでぜひチェックしてください。
「例外処理」とは
例外処理って何だろう
そもそもの話になりますが、「例外処理」という言葉は聞いたことがあっても実際なんなのか説明してと言われるとちょっと悩みます。
簡単に言うと、例外処理とはプログラムの実行時に発生した問題に対応できるようにしておくことをいいます。……よく分からない?では、もう少し具体的に説明します。
C#ではコードをコンピュータが実行できる形にするためにコンパイルをおこない、コンパイルが正常に終われば処理を実行することができます。例外というのは、コンパイルの問題ではなくプログラム実行時の問題を指します。
C#入門編10: 例外処理を理解しよう「01:例外処理の概要を理解しよう」より
ちなみに、コンパイルをしないプログラミング言語(PHPやPythonなど)もありますので、言語によってこのへんはちょっと違ってきます。
ありがちな例外発生の例としては以下が挙げられます。
C#入門編10: 例外処理を理解しよう「01:例外処理の概要を理解しよう」より
上の図に書かれている「計算できない」「ファイルがない」などの問題が発生したときに、たとえば「処理をそこで中断して、問題があったことをメッセージ表示する」という対応が例外処理です。
例外処理は必要か
例外処理が何者かなんとなく分かったところで気になるのが「例外処理は必要なのか?」ということです。
たしかにプログラムを実行して必ずすべての処理が正常に動作すると保証できれば必要ないかもしれません。もしくは問題があってプログラムが異常終了するのは仕方がないと思うこともできます。
個人で趣味の開発をおこなっているのであればそれでもいい場合がありますが、実務でのシステム開発となると話は違ってきます。たとえば例外処理をおこなっていないと…
- 画面操作が不能になりユーザーでは対処できないため業務に支障をきたす
いわゆる「システム障害」で続行不能となった状態をいいます。アプリケーションを利用しているユーザーからは対処ができません。たとえば、Webアプリケーションであればブラウザを閉じるしかないような状態です。
受託開発で納品したシステムの場合、システム障害となり顧客業務が滞ってしまうと、影響度の大きさにもよりますが損害賠償請求などに発展する可能性もあります。
- 問題の原因調査および特定ができないもしくは難しくなる
例外処理が適切に実装できていないと、異常が発生した箇所の特定ができず対策に時間がかかってしまいます。
限られた条件下で発生する場合などは事象の再現が難しいため例外発生時のログに出力される内容が重要になってきます。
結論としては、例外処理は必要ということになります。ただし、過剰に例外処理を書けばいいというわけでもありません。その名のとおり例外的な条件にのみ適用し通常の処理フローで使うべきではないと心得ておきましょう。
また、書き方によっては発生した例外を無視して処理の続行ができてしまうため(例外を握りつぶす、と表現します)その点にも気をつける必要があります。
C#で例外処理を書いてみよう
理論より実際書いたほうが分かりやすいと思いますので、ここからは例外処理を書いて実行してみましょう。
例外を発生させてみる
C#では例外処理(Exception)をtry・catch・throwを使って記述します。
C#入門編10: 例外処理を理解しよう「01:例外処理の概要を理解しよう」より
paiza.ioを使うと環境構築不要でブラウザ上でプログラムが実行できますので、皆さんも手を動かしながら読み進めてみてください。
paiza.ioを開いていただくと「コードを作成してみる(無料)」というボタンがありますので、クリックするとコードを書いて実行できる画面が表示されます。左上のプルダウンメニューから「C#」を選択したら準備完了です。(登録なしでも利用できますが、登録してログイン状態で使っていただくと実行したコードが保存されます)
まず、単純な割り算をするプログラムを書いてみます。number変数は標準入力で取得します。paiza.ioを開いてくださっている方は、画面下部に「入力」タブがありますので、そこに「10」と入力してから実行してください。
public class Hello{ public static void Main(){ { int number = int.Parse(System.Console.ReadLine()); // 標準入力で値を受け取る int answer = 100 / number; // 100割るnumberを実行 System.Console.WriteLine(answer); // 計算結果を出力 } } }
与えられる値が「10」のときは正常に処理され出力結果は以下になります。paiza.ioでは、画面下部の「出力」タブに表示されます。
10
このとき「例外」が発生する条件としてはどんなことが考えられるでしょうか?
割り算といえば…そう、「0」での割り算が発生する可能性がありますね。まずは、上記のプログラムのままnumberに「0」を与えてみます。
paiza.ioの画面下部の「入力」タブに切り替え「0」と書いて再度実行してください。
Unhandled Exception: System.DivideByZeroException: Attempted to divide by zero. at Hello.Main () [0x0000d] in /workspace/Main.cs:6 [ERROR] FATAL UNHANDLED EXCEPTION: System.DivideByZeroException: Attempted to divide by zero. at Hello.Main () [0x0000d] in /workspace/Main.cs:6
すると処理が中断されて「ハンドルされない例外(キャッチできなかった例外)」と表示されました。では、例外処理で対応できるように実装してみましょう。tryとcatchはこのように使います。
public class Hello{ public static void Main(){ /* try: 例外が発生する可能性のある箇所 */ try { int number = int.Parse(System.Console.ReadLine()); // 標準入力で値を受け取る int answer = 100 / number; // 100割るnumberを実行 System.Console.WriteLine(answer); // 計算結果を出力 } /* catch: 例外発生時の対応処理を記述する */ catch { System.Console.WriteLine("エラー: 0除算が発生しました!"); // エラーメッセージの出力 } } }
catchでの処理を記述しましたが、与えられる値が「10」のままであれば、100割る10は正常に処理できるため実行結果はさきほどと同じです。つまり、例外は発生せずcatchの中は実行されません。
それでは、与えられる値が「0」のときはどうなるでしょうか。上のプログラムを実行すると…
エラー: 0除算が発生しました!
100割るnumberの処理で、numberが「0」だったためcatchの中に定義したエラーメッセージが表示されました。
上のプログラムではcatchに引数はなく、またエラーメッセージは自分で定義しました。それでもtry-catchはできているのですが、C#にはExceptionクラスというものが用意されており、どんな例外が発生したか、エラーが発生した理由・原因は何かの情報を知ることができるのでそれを使う方法も紹介しておきます。
public class Hello{ public static void Main(){ /* try: 例外が発生する可能性のある箇所 */ try { int number = int.Parse(System.Console.ReadLine()); // 標準入力で値を受け取る int answer = 100 / number; // 100割るnumberを実行 System.Console.WriteLine(answer); // 計算結果を出力 } /* catch: 例外発生時の対応処理を記述する */ catch (System.Exception e) //Exceptionクラスで例外をキャッチする { System.Console.WriteLine(e.Message); // エラーメッセージの出力 } } }
メッセージ内容を自分で定義しなくても、Exceptionクラスが0除算が発生したことを特定し以下のようなメッセージを表示してくれます。
Attempted to divide by zero.
Exceptionクラスには0で割り算をしたとき(DivideByZeroException)だけでなく、指定したファイルが存在しない(FileNotFoundException)、指定したファイルがロックされている(IOException)などの例外もキャッチして、該当するエラーメッセージを表示します。
例外にはいろいろな種類があります。動画講座で詳しく説明していますので、実際にコードを書いて実行しながら学んでみてください。
なお、Exceptionクラスを使うとほとんどどんな例外でもキャッチして例外の種類と例外が発生した箇所(コードのどの部分か)が分かるので、便利に思えるのですが…公式では推奨されていません。Exceptionクラスを継承しているそれぞれの例外クラスでキャッチしたほうがよいでしょう。
例外のクラス構成については以下のチャプターで説明しています。
このあたりは少し難しい話になるので、プログラミング学習が進んでからもう一度思い出してみてもいいかもしれません。
<参考サイト>
(補足)Visual Studioのデバッグ機能で例外処理を管理する
実務においてC#で開発をおこなう場合、Visual Studio(Microsoftが提供している統合開発環境)を利用することが多いと思います。
プログラムを書いて一発でコンパイルがとおり正常に実行させる…というのはなかなか難しく、どこかに問題がありそれを修正するという作業が発生します。
Visual Studioのデバッグ機能は慣れるまで難しいと感じることもあり初心者の方が手こずることが多いです。ただ、使いこなせればエラー原因の特定や、対処が格段にやりやすくなりますのでぜひマスターしてみてください。
公式ドキュメントも充実していますのでいくつか紹介します。
まとめ
C#の例外処理について学んできました。プログラミング学習を始めたばかりのころは後回しになりがちですが、システム開発には欠かせない内容ですのでpaizaラーニングの講座も活用しながら理解を深めていってくださいね。
冒頭でも述べたとおり、本記事ではC#を取り上げましたが例外処理の講座は他の言語もありますので、合わせてチェックしてください。
「paizaラーニング」では、未経験者でもブラウザさえあれば、今すぐプログラミングの基礎が動画で学べるレッスンを多数公開しております。
そして、paizaでは、Webサービス開発企業などで求められるコーディング力や、テストケースを想定する力などが問われるプログラミングスキルチェック問題も提供しています。
スキルチェックに挑戦した人は、その結果によってS・A・B・C・D・Eの6段階のランクを取得できます。必要なスキルランクを取得すれば、書類選考なしで企業の求人に応募することも可能です。「自分のプログラミングスキルを客観的に知りたい」「スキルを使って転職したい」という方は、ぜひチャレンジしてみてください。