自分のクラス 。 例外に直接基づいてではなく、
Exception
から継承した独自のクラスに基づいて例外をスローします。これにより、独自のハンドラーを定義し、コードと.NETフレームワークのコードによってスローされた例外の追跡と処理を分離できるためです。
個別のフィールド 。
Message
フィールドのデータをシリアライズおよびデシリアライズする代わりに、独自のクラスに個別のフィールドを作成して、重要な情報を伝えます。 複雑な
Message
データを
Message
のJSON文字列としてパックするという考えは魅力的ですが、エンコード、ローカライズ、およびデコードのためのリソースの追加コストが追加されるため、これはめったに良いアイデアではありません。
ログへのメッセージ 。 ハンドラーが
Exception.ToString();
呼び出して
Exception.ToString();
キャッチするたびにメッセージを記録します
Exception.ToString();
これにより、例外のデバッグ時に追跡が容易になります。
正確なクラス 。 最も一般的でないクラスを使用して例外をキャッチします。そうしないと、検出が困難なエラーが発生する可能性があります。 次のコードを検討してください。
public class SimpleClass { public static string DoSomething() { try { return SimpleLibrary.ReportStatus(); } catch (Exception) { return "Failure 1"; } } } public class SimpleLibrary { public static string ReportStatus() { return String.Format("Success {0}.", 0); } }
SimpleClass
SimpleLibrary
と
SimpleLibrary
のコードが別々のアセンブリにあると仮定した場合、両方のアセンブリが正しくインストールされた場合、コードは正しく実行され、メッセージ「Success 0」が表示され、
SimpleLibrary
クラスのアセンブリがインストールされなかった場合、コードは正しく実行されません。
ReportStatus
関数の実行中にエラーが発生しなかったにもかかわらず、「Failure 1」というメッセージが表示されます。 過度に一般化された例外処理のため、問題は明らかではありません。 行をフォーマットするコードは
ArgumentNullException
および
FormatException
スロー
FormatException
ため、catchブロックでキャッチする必要があるのはこれらの例外です。エラーの原因は明白になります。これは
SimpleLibrary
クラスを含むアセンブリの不在または誤ったインストールによる
FileNotFoundException
例外です。
実質的な処理 。 常に例外を情報に基づいて処理します。 コードを表示
try { DoSomething(); } catch (SomeException) { // TODO: ... }
問題を隠し、デバッグまたは実行中に検出されないようにします。
finally
ブロックでクリアします 。
finally
ブロックの一時オブジェクトを削除します。 一時ファイルを書き込む操作を検討してください。
void WorkWithFile(string filename) { try { using (StreamWriter sw = new StreamWriter(filename)) { // TODO: Do something with temporary file } File.Delete(filename); } catch (Exception) { File.Delete(filename); throw; } }
ご覧のとおり、ファイルを削除するコードが重複しています。 繰り返しを避けるために、
finally
ブロックから一時ファイルを削除する必要があります。
void WorkWithFile(string filename) { try { using (StreamWriter sw = new StreamWriter(filename)) { // TODO: Do something with temporary file } } finally { File.Delete(filename); } }
ステートメントを使用する
using
ステートメントを使用します。 オブジェクトのメソッドを呼び出すときに例外が発生した場合でも、
Dispose
メソッドの呼び出しを保証します。
using (Font f = new Font("Times New Roman", 12.0f)) { byte charset = f.GdiCharSet; }
using
ステートメントの使用は、
try/finally
ブロック
try/finally
同等ですが、よりコンパクトで簡潔です。
Font f = new Font("Times New Roman", 12.0f); try { byte charset = f.GdiCharSet; } finally { if (f != null) ((IDisposable)f).Dispose(); }
関数の結果 。 関数の結果を返すために例外を使用したり、エラーを処理するために特別なリターンコードを使用したりしないでください。 それぞれに-彼自身。 関数の結果を返す必要があり、スキップできないエラーは例外で処理する必要があります。
リソース不足 。 リソースがない場合は
null
返し
null
。 .NET APIで一般的に受け入れられている規則によれば、関数はリソースがない場合に例外をスローしてはならず、
null
を返す必要があり
null
。 その
GetManifestResourceStream
、リソースがコンパイル時に指定されなかった場合、または呼び出し元のコードから見えない場合、
GetManifestResourceStream
は
null
返し
null
。
出発地 。 例外が発生した場所を追跡します。 例えば
try { // Do something to throw exception } catch (Exception e) { // Do something to handle exception throw e; // Wrong way! throw; // Right way }
コールスローの場合、
throw e;
新しい例外を作成するとコールスタックがクリアされるため、例外がスローされる場所に関する情報は新しい行に置き換えられます。 代わりに、
throw;
呼び出しを行う必要があります
throw;
単に元の例外をスローします。
意味を追加します。 元の例外を変更して、ユーザーが必要とする意味を追加します。 たとえば、データベースに接続する場合、ユーザーは接続障害の原因(ソケットエラー)、障害自体に関する十分な情報に無関心かもしれません。
連載
[Serializable]
で例外を継承可能
Exception
例外に継承可能にし
Exception
。 これは、Webサービスなどで例外が受信される場所が事前にわからないため、便利です。
[Serializable] public class SampleSerializableException : Exception { public SampleSerializableException() { } public SampleSerializableException(string message) : base(message) { } public SampleSerializableException(string message, Exception innerException) : base(message, innerException) { } protected SampleSerializableException(SerializationInfo info, StreamingContext context) : base(info, context) { } }
標準コンストラクタ 。 標準のコンストラクタを実装します。そうしないと、正しい例外処理が困難になる場合があります。 したがって、
NewException
を除外する
NewException
これらのコンストラクターは次のとおりです。
-
public NewException();
-
public NewException(string);
-
public NewException(string, Exception);
-
protected or private NewException(SerializationInfo, StreamingContext);
MSDN、CodeProject、StackOverflowの資料に基づいています。