C#のcatch節で複数例外をキャッチする方法を初心者向けにやさしく解説!
生徒
「C#でエラーが起きたときに、どんなエラーかによって分けて処理したいんですが、どうしたらいいですか?」
先生
「いい視点ですね。C#ではcatch節を複数書くことで、エラーの種類に応じて個別に処理できますよ。」
生徒
「複数ってどういうことですか?ひとつだけじゃなくていいんですか?」
先生
「もちろん。例外の種類ごとにcatch節を分けて書けるんです。実際に例を見ながら学んでみましょう!」
1. 例外(エラー)とは何か?
プログラムを実行しているときに、想定外の出来事が起きて処理が止まってしまうことがあります。たとえば、ファイルが見つからない、ゼロで割った、などです。こうした予期しない出来事を「例外(れいがい)」と呼びます。
C#では、例外が発生するとプログラムはエラーになり、そのままでは止まってしまいます。そこで、try-catchという仕組みを使って、例外をキャッチ(つかまえる)し、適切に処理することができます。
2. catch節を使って例外を処理する基本形
try-catch構文は、エラーが起こりそうなコードをtryブロックに書いて、その後にcatchで処理をします。以下が基本の形です。
try
{
// エラーが起こるかもしれない処理
}
catch (Exception ex)
{
// 例外が発生したときの処理
}
Exceptionは、すべての例外の親(親クラス)です。どんな例外でもこのcatchで受け取ることができますが、もっと詳しく分けて処理する方法もあります。
3. 複数の例外をcatch節で分けて処理する
C#では、例外の種類に応じて複数のcatch節を書くことができます。たとえば、ゼロで割ったときのエラー(DivideByZeroException)と、配列の範囲外にアクセスしたときのエラー(IndexOutOfRangeException)を別々に処理できます。
try
{
int[] numbers = { 1, 2, 3 };
int result = numbers[5] / 0; // 配列の範囲外アクセス+ゼロ割り
}
catch (DivideByZeroException ex)
{
Console.WriteLine("ゼロで割ることはできません。");
}
catch (IndexOutOfRangeException ex)
{
Console.WriteLine("配列の範囲外にアクセスしました。");
}
catch (Exception ex)
{
Console.WriteLine("その他のエラーが発生しました。");
}
配列の範囲外にアクセスしました。
このように、catch節は上から順番に評価され、最初に一致したものだけが実行されます。
4. Exceptionの種類と使い分け
C#にはたくさんの例外クラスがありますが、よく使う例をいくつか紹介します。
DivideByZeroException:ゼロで割ったときの例外IndexOutOfRangeException:配列の範囲外アクセスNullReferenceException:nullの変数にアクセスしたときFormatException:文字列を数値に変換できなかったとき
これらを意識してcatch節を分けることで、より安全で分かりやすいコードが書けるようになります。
5. 例外クラスの親子関係に注意しよう
すべての例外クラスは、System.Exceptionクラスを基に作られています。たとえば、DivideByZeroExceptionもExceptionの子供(子クラス)です。
そのため、より具体的な例外(子クラス)を先に書く必要があります。でないと、親クラスのcatchで処理されてしまい、子クラスのcatchは実行されません。
try
{
int zero = 0;
int result = 10 / zero;
}
catch (Exception ex)
{
Console.WriteLine("親のcatchです。");
}
catch (DivideByZeroException ex)
{
// これは実行されません!
Console.WriteLine("ゼロ割りです。");
}
親のcatchです。
このように、catch節は子クラス → 親クラスの順番で書くのが基本です。
6. すべての例外をまとめて処理したいときは?
特に種類を気にせず、すべてのエラーをまとめて処理したいときは、最後にExceptionを指定してcatchすることができます。
たとえば、ログを残す、エラーを通知する、といった用途で使います。
try
{
// いろいろな処理
}
catch (Exception ex)
{
Console.WriteLine("エラーが発生しました:" + ex.Message);
}
7. 複数のcatchでスマートにエラー対応しよう
プログラムでは、起こりうるトラブルに対して備えることがとても大事です。catch節を複数用意しておけば、どのエラーかによって処理を変えることができ、ユーザーにも分かりやすいメッセージを表示できます。
さらに、例外の内容を記録しておけば、後からバグの原因を調べることも可能です。ex.Messageを使えば、実際のエラーメッセージを表示できます。
まとめ
C#のcatch節を使った複数例外処理は、プログラムの安全性と信頼性を高めるために欠かせない基本技術です。これまで解説してきたように、例外はプログラム実行中に発生する予期しない出来事であり、その内容や原因は多種多様です。ファイル操作中のエラー、配列アクセスのミス、文字列変換の失敗、ゼロ除算など、実際のアプリケーションではさまざまな例外が発生します。こうした異なるエラーに対して適切な対応を行うためには、catch節で例外を使い分ける設計が重要になります。 特に、例外クラスには明確な親子関係があり、より具体的な例外(子クラス)から処理し、最後に大きなくくりであるException(親クラス)でまとめることが基本です。この順番を正しく理解して使うことで、意図通りに例外処理が動作し、必要なメッセージを表示したり、ログを残したりといった柔軟な対応ができます。また、例外ごとに別々の処理を行うことは、ユーザーフレンドリーなアプリケーションに欠かせません。どのエラーが起きたのかを丁寧に知らせることで、使用者にとって安心感のある動作になります。 さらに、Webアプリケーションやデスクトップアプリケーションでは、予測できない状況が起こることも多く、例外処理の精度がそのままアプリケーションの品質に直結します。ログ記録やエラーハンドリングの仕組みを確立する際にも、どの例外をどこで処理するのかを明確にしておくことで、デバッグ作業を効率化できるという利点もあります。このように、catch節を使いこなすことは、初心者から中級者へとステップアップするためのとても大切なポイントになります。 catch節を複数記述するときの書き方そのものはシンプルですが、実際に使いこなすためには、どの例外クラスがどのような状況で発生するのかを理解することが重要です。たとえば、DivideByZeroExceptionは計算処理で起きやすく、IndexOutOfRangeExceptionは配列操作において頻出します。FormatExceptionは文字列を数値に変換する場面でよく見られ、NullReferenceExceptionは初学者が最もつまずきやすい例外のひとつです。これらを使い分けることで、細やかで精度の高いエラー処理が書けるようになります。 また、例外処理の中ではex.Messageを活用し、発生したエラーの詳細をログに記録することも非常に効果的です。ログは後から問題の元を解析するための重要な手がかりとなり、開発チームや運用担当者が原因を特定するための大きな助けとなります。例外処理を適切に行うことは、チーム開発や大規模システムの運用においても長期的なメリットを生み出します。 ここでは、複数例外をキャッチして処理内容を分ける応用的なサンプルコードを紹介します。例外ごとに動作が違う実例を確認することで、catch節の仕組みをより深く理解できます。
複数例外を安全に処理するサンプルコード
using System;
using System.IO;
class Program
{
static void Main()
{
try
{
Console.WriteLine("ファイルを読み込みます…");
string text = File.ReadAllText("sample.txt");
Console.WriteLine("文字列を数値に変換します…");
int value = int.Parse(text);
Console.WriteLine("計算をします…");
int result = 100 / value;
Console.WriteLine("計算結果:" + result);
}
catch (FileNotFoundException ex)
{
Console.WriteLine("ファイルが見つかりませんでした。");
Console.WriteLine("詳細:" + ex.Message);
}
catch (FormatException ex)
{
Console.WriteLine("文字列を数値に変換できませんでした。");
Console.WriteLine("詳細:" + ex.Message);
}
catch (DivideByZeroException ex)
{
Console.WriteLine("ゼロで割ることはできません。");
Console.WriteLine("詳細:" + ex.Message);
}
catch (Exception ex)
{
Console.WriteLine("予期しないエラーが発生しました。");
Console.WriteLine("詳細:" + ex.Message);
}
finally
{
Console.WriteLine("処理を終了します。");
}
}
}
このコードでは、ファイル操作・文字列解析・数値計算という異なる場面でエラーが起きる可能性を想定し、catch節を段階的に分けて処理しています。例外ごとに違うメッセージを表示することで、原因がすぐに判断でき、デバッグ作業やユーザーへの説明も行いやすくなります。こうした実践的な例外処理の使い分けは、システム開発全体の品質を大幅に高める力を持っています。 複数例外のキャッチは難しく見えるかもしれませんが、例外クラスの特徴を理解しながら組み合わせていくことで自然と書けるようになります。今後、複雑なアプリケーションを作るときにも役立つスキルなので、身につけておくと大きな強みになります。
生徒
「catch節ってひとつだけだと思っていましたが、種類ごとに分けて書けるのは便利ですね!」
先生
「そうですね。例外ごとに処理を変えることで、より正確で使いやすいプログラムになりますよ。」
生徒
「例外クラスの親子関係を意識して書くことも大事なんですね。順番を間違えると意図通りに動かないのは驚きでした。」
先生
「その通りです。具体的な例外から先に書き、最後にExceptionでまとめるという考え方はとても重要です。」
生徒
「ファイルエラーや計算エラーなど、実際の場面をイメージしながら学べると理解しやすいですね。」
先生
「例外処理はアプリの安定性にも直結するので、これからも実例を交えてしっかり覚えていきましょう。」