工業製造
産業用モノのインターネット | 工業材料 | 機器のメンテナンスと修理 | 産業プログラミング |
home  MfgRobots >> 工業製造 >  >> Industrial programming >> C言語

C#の例外処理:try/catch/finally/throwとベストプラクティス

例外とは、プログラムの実行中に発生する問題のことです。C#の例外は、プログラム実行中に発生する例外的な状況(ゼロ除算の試みなど)への応答です。

例外は、プログラムのある部分から別の部分へ制御を移す手段を提供します。C#の例外処理は4つのキーワードに基づいて構築されています:try、catch、finally、throw。

構文

ブロックが例外を発生させると仮定すると、メソッドはtryとcatchキーワードの組み合わせで例外を捕捉します。try/catchブロックは例外を生成する可能性のあるコードの周りに配置します。try/catchブロック内のコードは保護されたコードと呼ばれ、try/catchの使用構文は以下のようになります。

try {
    // 例外を引き起こす可能性のあるステートメント
} catch (ExceptionName e1) {
    // エラー処理コード
} catch (ExceptionName e2) {
    // エラー処理コード
} catch (ExceptionName eN) {
    // エラー処理コード
} finally {
    // 実行されるステートメント
}

tryブロックで異なる状況で複数の種類の例外が発生する可能性がある場合、複数のcatchステートメントを記述できます。

C#の例外クラス

C#の例外はクラスで表現されます。C#の例外クラスは主にSystem.Exceptionクラスから直接的または間接的に派生しています。System.Exceptionクラスから派生した例外クラスには、System.ApplicationExceptionとSystem.SystemExceptionクラスがあります。

主要な定義済み例外クラス(System.SystemException派生)

No.例外クラスと説明
1System.IO.IOException - I/Oエラーを処理
2System.IndexOutOfRangeException - 配列インデックスが範囲外のとき
3System.ArrayTypeMismatchException - 型が配列型と不一致のとき
4System.NullReferenceException - nullオブジェクトを参照したとき
5System.DivideByZeroException - ゼロ除算のとき
6System.InvalidCastException - 型キャスト時のエラー
7System.OutOfMemoryException - 空きメモリ不足
8System.StackOverflowException - スタックオーバーフロー

例外処理の例

ゼロ除算条件が発生したときに例外をスローする例です。

using System;
namespace ErrorHandlingApplication {
    class DivNumbers {
        int result;
        
        DivNumbers() { result = 0; }
        
        public void Division(int num1, int num2) {
            try {
                result = num1 / num2;
            } catch (DivideByZeroException e) {
                Console.WriteLine("Exception caught: {0}", e);
            } finally {
                Console.WriteLine("Result: {0}", result);
            }
        }
        
        static void Main(string[] args) {
            DivNumbers d = new DivNumbers();
            d.Division(25, 0);
            Console.ReadKey();
        }
    }
}

実行結果:

Exception caught: System.DivideByZeroException: Attempted to divide by zero.
Result: 0

ユーザー定義例外の作成

独自の例外を定義することもできます。ユーザー定義例外クラスはExceptionクラスから派生させます。

using System;
namespace UserDefinedException {
    class TestTemperature {
        static void Main(string[] args) {
            Temperature temp = new Temperature();
            try {
                temp.ShowTemp();
            } catch (TempIsZeroException e) {
                Console.WriteLine("TempIsZeroException: {0}", e.Message);
            }
            Console.ReadKey();
        }
    }
}

public class TempIsZeroException : Exception {
    public TempIsZeroException(string message) : base(message) { }
}

public class Temperature {
    int temperature = 0;
    
    public void ShowTemp() {
        if (temperature == 0) {
            throw new TempIsZeroException("Zero Temperature found");
        } else {
            Console.WriteLine("Temperature: {0}", temperature);
        }
    }
}

実行結果:

TempIsZeroException: Zero Temperature found

例外フィルター(C# 6.0以降)

whenキーワードを使用して、特定の条件下でのみcatchブロックを実行できます。

try {
    // 何らかの処理
} catch (SqlException ex) when (ex.Number == 2627) {
    // 主キー重複エラーのみ処理
    Console.WriteLine("Duplicate key error");
} catch (SqlException ex) when (ex.Number == 547) {
    // 外部キー制約違反のみ処理
    Console.WriteLine("Foreign key violation");
} catch (SqlException ex) {
    // その他のSQL例外
    Console.WriteLine($"SQL Error: {ex.Number}");
}

例外の再スロー

catchブロックでthrowを使用して、現在の例外を上位に伝播できます。

try {
    // 処理
} catch (Exception e) {
    // ログ記録など
    Logger.Log(e);
    throw;  // 元のスタックトレースを保持して再スロー
    
    // throw e;  // ❌ スタックトレースがリセットされる(非推奨)
}

例外オブジェクトのスロー

System.Exceptionクラスから直接的または間接的に派生したオブジェクトであればスローできます。

catch (Exception e) {
    // 何らかの処理
    throw e;  // 現在の例外オブジェクトをスロー
}

usingステートメントとIDisposable(リソース確実解放)

finallyでリソースを解放する代わりに、usingステートメントを使用するとより安全かつ簡潔です。

// 従来の書き方
FileStream fs = null;
try {
    fs = new FileStream("test.txt", FileMode.Open);
    // 処理
} finally {
    fs?.Dispose();
}

// usingステートメント(推奨)
using (FileStream fs = new FileStream("test.txt", FileMode.Open)) {
    // 処理
}  // 自動的にDispose()が呼ばれる

// C# 8.0以降:using宣言
using var fs = new FileStream("test.txt", FileMode.Open);
// スコープ終了時に自動Dispose

ベストプラクティス

例外処理のアンチパターン

C言語

  1. PLCとDCS:適切なオートメーションシステムの選び方
  2. Liebherr PHS Allround:大容量生産向けの柔軟・モジュール式パレットハンドリング
  3. Liebherr、パレットハンドリングシステム拡充でフレキシブル生産を強化
  4. C# usingステートメント完全ガイド:名前空間インポート、エイリアス、静的ディレクティブ
  5. C言語 ファイル入出力: fopen, fprintf, fread, fseek をマスターする
  6. C++例外処理をマスター:try、catch、throwの実践例
  7. C++シグナル処理をマスター:安全な割り込み管理とクリーンなプログラム終了
  8. Python例外処理マスター:try、except、else、finallyを徹底解説
  9. Python例外処理をマスター:try、except、finally、raiseの効果的な活用
  10. Java例外ハンドリング完全攻略:try-catch、finally、throw、throws
  11. Java 9モジュールシステム:リンクタイムとカスタムランタイムイメージ