例外処理、try-catch文を理解しよう!

[C#] 例外処理、try-catch文を理解しよう!

※ 当サイトは広告を含みます。

ここではC#の例外処理について学びます。すでに少しだけ触れてますが、これは実行時エラーへの対策となります。
ただ、例外処理もクラスの知識を必要とします。そのため60%くらいの解説になりますが、今はここまでいいと思ってます。

例外 (Exception)

C#では実行時に発生するエラーを例外と言います。僕が知ってる他の言語も大半が同じだった気がします。
この例外とは、特定の条件において処理を完了できない問題が起きると発生し、その例外を誰もcatch(キャッチ)しないとプログラムが強制終了します。

catchについては後で説明しますが、例外が発生する処理とは何でしょうか。いくつか例を書くので確認してみましょう。

  1. 変換できない文字列を数値に変換しようとした。
  2. 配列で存在しないインデックスにアクセスしようとした。
  3. 値がnullなのに参照アクセスしようとした。

などなど。このようなことをプログラムで実行すると例外が発生します。

これは以前に試した、入力された文字列を数値に変換するサンプルコードです。
この時に数値に変換できない文字列だと例外が起きてましたよね。


namespace Sample
{
  internal class Program
  {
    static void Main(string[] args)
    {
      string s = Console.ReadLine();

      int n = int.Parse(s);
      Console.WriteLine(n);
    }
  }
}
りさ
りさ

例外が発生する条件って分かるんですか?

管理人
管理人

分かります。嫌だと思うけど次のリンク先のExceptionsって部分を見ましょう。
https://learn.microsoft.com/en-us/dotnet/api/system.int32.parse

りさ
りさ

英語だ...

管理人
管理人

しょうがないな。一部を画像で切り抜いてあげよう。

公式ドキュメント
管理人
管理人

これが1次ソース、つまり公式ドキュメントのint.Parse()の解説です。
ここでは深くは言いませんが、困ったら公式ドキュメントを見る癖をつけましょう。

という事で、int.Parse()の公式ドキュメントには以下の4つの例外が発生することが書かれてます。

  1. ArgumentNullException
  2. ArgumentException
  3. FormatException
  4. OverflowException

ここでは内容は触れませんが、例外には種類があって元から想定された例外が発生すると理解してください。

catch

これは発生した例外を捕まえることを言います。

例外とはある場所を起点に発生し、誰もcatchしないと永遠と上位へ渡っていきます。
その結果、上り続けた例外がMain関数すら超えると、プログラムは強制終了で落ちます。

例えば、Main関数からFunction1関数、さらにFunction2関数を呼び出し、そこで例外が発生した場合を考えましょう。

例外発生

これをcatchするために、それ専用の構文が存在します。それがtry-catch文です。

try-catch

先に構文とサンプルコードを確認しましょう。

try-catch

namespace Sample
{
  internal class Program
  {
    static void Main(string[] args)
    {
      string s = Console.ReadLine();

      try
      {
        int n = int.Parse(s); // 例外の可能性がある

        Console.WriteLine(n);
      }
      catch
      {
        // 例外が発生した場合の処理
        Console.WriteLine("例外が発生しました。");
      }
    }
  }
}

このように例外を発生させる可能性がある場所をtryで囲みます。
そして続けてcatchを書くことで、例外発生時の対処を記述することができます。

りさ
りさ

もしかしてMain関数を全部tryで囲っておけば安全では!

管理人
管理人

そこに気がつくとは天才。ぶっちゃけ賛否両論なんだけど、何もしないよりはオススメだよ。
もちろん全部を囲むならcatchの中で原因を特定できる記録を残さないと駄目だよ。

Tipstry-catchはネスト構造にもできます。その場合は、専用の構文(throw)を使って上位のtry-catchに例外を投げることができます。

try-catch-finally

tryで例外が発生すると無条件でcatchに流れます。この時に終了処理みたいな、絶対に実行したい処理がある場合、どうしたらいいのでしょうか。
安心してください。それ用の構文が用意されてます。それがtry-catch-finallyです。

では、構文とサンプルコードを確認しましょう。

try-catch-finally

namespace Sample
{
  internal class Program
  {
    static void Main(string[] args)
    {
      string s = Console.ReadLine();

      try
      {
        int n = int.Parse(s); // 例外の可能性がある

        Console.WriteLine(n);
      }
      catch
      {
        // 例外が発生した場合の処理
        Console.WriteLine("例外が発生しました。");
      }
      finally
      {
        // 必ず実行する処理
        Console.WriteLine("終了処理");
      }
    }
  }
}

finallyが追加されてるだけなので問題ないですよね。
このfinallyは例外の発生に関わらず必ず実行されます。

例外とエラー

例外とエラー、似てるとは思いませんか? よくある定義だと、例外は想定していたエラー、エラーは想定してなかったエラーと言われます。
つまり例外は予め発生する要因が分かってるから対策が可能であり、エラーは本当に不明だったから対策できなかった的なやつです。

りさ
りさ

よく分からないよ。

管理人
管理人

僕もよく分からないよ。

りさ
りさ

えぇ...

管理人
管理人

たぶん宗教問題だよ。

あとがき

今の知識に合わせて一部を省いて説明しました。それでも基本的な使い方は書いたつもりです。
別のタイミングで追加の情報をまとめるので、その時に改めて学習しましょう。

◆ C#に関する学習コンテンツ

この記事は参考になりましたか?

関連記事

コメント

この記事へのコメントはありません。