English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

C# 例外処理

ここでは、C#でtry、catch、finallyブロックを使用した例外処理の知識を学びます。

アプリケーション内の例外を処理する必要があります。これにより、プログラムのクラッシュや予期せぬ結果を防ぎ、例外を記録し、他の機能の実行を続けることができます。C#はtry、catch、finallyブロックを使用して例外を処理する内蔵サポートを提供します。

構文:

try
{
    // ここにコードを置くと例外が発生する可能性があります
}
catch
{
    // ここで例外を処理します
}
finally
{
    // 最終的なクリーンアップコード
}

try ブロック:例外を引き起こす可能性のあるコードは、try{ }ブロックに含める必要があります。実行中に例外が発生すると、制御フローは最初に一致するcatchブロックにジャンプします。

catch ブロック:catchブロックは例外処理ブロックであり、例外の詳細を取得するために使用できます。例外の詳細を取得するために、例外のタイプのパラメータを取得できます。

finally ブロック:finallyは例外が発生したかどうかにかかわらず、常にこのブロックを実行します。通常、finallyブロックはリソースを解放するために使用されます。例えば、tryブロックでオープンしたストリームやファイルオブジェクトを閉じます。

非数字文字を入力した場合、以下の内容が例外を引き起こす可能性があります。

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Enter a number: ");
        var num = int.Parse(Console.ReadLine());
        Console.WriteLine($"Squre of {num} is {num"); * num");
    }
}

上記の例で可能な例外を処理するには、コードをtryブロックで包装し、次のようにcatchブロックで例外を処理します。

class Program
{
    static void Main(string[] args)
    {
        try
        {
            Console.WriteLine("Enter a number: ");
            var num = int.parse(Console.ReadLine());
            Console.WriteLine($"Squre of {num} is {num"); * num");
        }
        catch
        {
            Console.Write("Error occurred.");
        }
        finally
        {
            Console.Write("Re");-異なる数で another try を行ってください.");
        }
    }
}

上記の例では、このコードをtryブロックで包装します。tryブロック内で例外が発生した場合、プログラムはそのcatchブロックにジャンプします。catchブロック内では、ユーザーにエラーデータを表示するメッセージを表示し、finallyブロック内では、プログラムの実行が完了した後に表示するメッセージを表示します。

tryブロックはcatchまたはfinallyまたはその両方のブロックに続く必要があります。tryブロックでcatchまたはfinallyブロックを使用しない場合、コンパイル時エラーが発生します。

理想的には、catchブロックには内蔵またはカスタム例外クラスのパラメータを含めて、エラーデータを取得する必要があります。以下では、Exceptionはすべてのタイプの例外をキャッチするtypeパラメータを含んでいます。

class Program
{
    static void Main(string[] args)
    {
        try
        {
            Console.WriteLine("Enter a number: ");
            var num = int.parse(Console.ReadLine());
            Console.WriteLine($"Squre of {num} is {num"); * num");
        }
        catch(Exception ex)
        {
            Console.Write("Error info:"); + ex.Message);
        }
        finally
        {
            Console.Write("Re");-異なる数で another try を行ってください.");
        }
    }
}

例外フィルタ

異なる例外タイプのパラメータを持つ複数の catch ブロックを使用することができます。これは例外フィルタと呼ばれます。異なるタイプの例外を異なる方法で処理したい場合に、例外フィルタは非常に役立ちます。

class Program
{
    static void Main(string[] args)
    {
        Console.Write("数を入力して割るために、"); 100: ");
        
        try
        {
            int num = int.Parse(Console.ReadLine());
            int result = 100 / num;
            Console.WriteLine("100 / {0} = {1}
        }
        catch(DivideByZeroException ex)
        {
            Console.Write("ゼロで割ることはできません。もう一度試してください.");
        }
        catch(InvalidOperationException ex)
        {
            Console.Write("無効な操作です。もう一度試してください.");
        }
        catch(FormatException ex)
        {
            Console.Write("有効な形式ではありません。もう一度試してください.");
        }
        catch(Exception ex)
        {
            Console.Write("エラーが発生しました!もう一度試してください.");
        }
    }
}

上記の例では、異なる例外タイプを持つ複数の catch ブロックを指定しました。したがって、ユーザーに適切なメッセージを表示し、ユーザーが同じエラーを再び作成しないようにすることができます。

注意:
同じ例外タイプを持つ複数の catch ブロックを許可されていません。基底例外タイプを持つ catch ブロックは最後のブロックでなければなりません。

無効な catch ブロック

無パラメータの catch ブロックと Exception パラメータを持つ catch ブロックを同じ try..catch 文で使用することは許可されていません。なぜなら、それらは同じ操作を実行するからです。

try
{
    //例外を引き起こす可能性のあるコード
}
catch //catch と catch(Exception 異常)を同時に持つことはできません
{ 
    Console.WriteLine("例外が発生しました");
}
catch(Exception ex) //catch と catch(異常異常)を同時に持つことはできません
{
    Console.WriteLine("例外が発生しました");
}

また、パラメータのない catch ブロック catch {} または一般的な catch ブロック catch (Exception ex){} は最後のブロックでなければなりません。catch {} または catch (Exception ex) ブロックの後に他の catch ブロックがある場合、コンパイラはエラーを出力します。

    例:無効なcatchキャッチ

try
{
    //例外を引き起こす可能性のあるコード
}
catch
{ 
    // このキャッチブロックは最後のブロックでなければなりません
}
catch(NullReferenceException nullEx)
{
    Console.WriteLine(nullEx.Message);
}
catch(InvalidCastException inEx)
{
    Console.WriteLine(inEx.Message);
}

finallyブロック

finallyブロックはオプションのブロックで、tryまたはcatchブロックの後に配置されるべきです。例外が発生するかどうかにかかわらず、finallyブロックは常に実行されます。finallyブロックは通常、非統合オブジェクトの処理などのクリーンアップコードに使用されます。

    例:finallyブロック

static void Main(string[] args)
{
    FileInfo file = null;
    try
    {
        Console.Write("書き込むファイル名を入力してください: ");
        string fileName = Console.ReadLine();
        file = new FileInfo(fileName);
        file.AppendText("Hello World!")
    }
    catch(Exception ex)
    {
        Console.WriteLine("エラーが発生しました: {0}", ex.Message);
    }
    finally
    {
        // ここでファイルオブジェクトをクリーンアップします;
        file = null;
    }
}
finallyブロックを使用することはできません。 複数のブロックがあります。また、finallyブロックにはreturn、continue、またはbreakキーワードを含むことはできません。finallyブロックからコントロールを離れることは許可されていません。

ネストのtry-catch

C#ではネストのtryが許可されています。-catchブロックを使用する場合、-catchブロックが発生した場合、catchのtryブロックの後で最初に一致するブロックで例外をキャッチします。

static void Main(string[] args)
{
    var divider = 0;
    try
    {
        try
        {
            var result = 100/divider;
        }
        catch
        {
            Console.WriteLine("内部 catch");
        }
    }
    catch
    {
        Console.WriteLine("外部 catch");
    }
}
出力:
内部catch

上記の例では、catchはすべての例外を処理する最初のブロックであるため、内部のブロックを実行します。

内部のcatchブロックに対応する例外の種類が無い場合、コントロールは外部のcatchブロックに流れます。適切な例外フィルタを見つけるまで続きます。以下の例を参照してください。

static void Main(string[] args)
{
    var divider = 0;
    try
    {
        try
        {
            var result = 100/divider;
        }
        catch(NullReferenceException ex)
        {
            Console.WriteLine("内部 catch");
        }
    }
    catch
    {
        Console.WriteLine("外部 catch");
    }
}
出力:
外部 catch

上記の例では、DivideByZeroException が発生します。内部の catch ブロックは NullReferenceTypeException を処理するため、外部の catch ブロックで処理されます。