4

私はすでに答えを知っていると確信していますが、Try、Catch、Finally ブロック内でエラーを処理することについての意見がどうなっているのか、まだ興味があります。

ところで-私はユーザー入力について話しているのではありません-しかし、それは明確で短いので、例として使用します

このコードを考えてみましょう...

try {    
    if (success) {
        return someSuccessMessage;
    }
    else {
        logError("User input not correct format");
        return someErrorMessage; // repeats itself
    }
}
catch (Exception ex) {
    logError(ex.Message);
    return someErrorMessage; // repeats itself
}

関数が失敗した場合、例外は無関係であるため、エラー メッセージを返したいとします。関数は成功せず、ユーザーは追加の詳細を必要としません。

私は常に、エラーを処理できる場合は例外を回避するという信念を持っていました-それはもはや例外的ではないためです.あなた自身...

try {    
    if (success) {
        return someSuccessMessage;
    }
    else {
        throw new Exception("User input not correct format");
    }
}
catch (Exception ex) {
    logError(ex.Message);
    return someErrorMessage;
}

これは最良の例ではありませんが、コードを繰り返すことを強調するために簡潔にするつもりでした。

例外はパフォーマンスの低下を招くことが知られていますが、このような状況についてはどう考えていますか?

4

6 に答える 6

4

ここで関心の分離に疑問を呈します。この関数が UI の一部でない限り、エラー メッセージに関係するべきではありません。代わりに例外をスローする必要があります。このメソッドの呼び出し元は、UI の一部である場合、表示用のエラー メッセージを生成する必要がある場合があります。呼び出し元が Web サービスである場合、同じメッセージを使用しない可能性がある SOAP Fault を生成する必要があります (メッセージがまったく使用されていない場合)。

また、ex.Message ではなく ex.ToString() をログに記録することを強くお勧めします。

于 2009-07-10T15:14:41.960 に答える
3

IMO、例外は、修正可能な状況の外にある場合にのみスローする必要があります。間違ったフォーマットを入力したユーザーは既知であり、例外をスローするべきではありません。

例外を壊滅的なものとして扱います(火災、地震などのデータセンター)。このように、「通常のエラー」と「例外」の処理の違いがわかります。

そして、はい、例外をスローしてキャッチすると、パフォーマンスが大幅に低下します。例外を回避するのが最善です。

于 2009-07-10T15:09:36.587 に答える
2

繰り返しが問題だと思われる場合は、重複したコードを関数に抽出します。

error_code_t fail (string message) {
    logError(message);
    return someErrorMessage;
}

// ...

try {    
    if (success) {
        return someSuccessMessage;
    }
    else {
        return fail("User input not correct format");
    }
}
catch (Exception ex) {
    return fail(ex.Message);
}

正直なところ、同じ関数内で数行を複製することについて心配する必要はありません。

于 2009-07-10T15:34:11.333 に答える
1

あなたの場合、エラーメッセージ(最初の例)を返すだけです。例外をスローして3行下でキャッチするだけで、少し奇妙に思えるからです。

まったく異なることは、通常、可能な場合はエラーコードを返さないようにすることです。エラーが発生した場合は、例外を通過して、可能な限り最高レベルでそれをキャッチします。このようにして、コードはどこでもエラー処理で散らかされることがなく、ビジネスロジックを確認するのがはるかに簡単になります。あなたの場合(もちろんそれを制御する場合)、成功を返すメソッドは失敗の場合に例外をスローする可能性があり、この質問をする必要はまったくありません:)

確かに、C#では例外は高額なので、悪用しないでください。そうは言っても、エラーが発生した場合、パフォーマンスの50ミリ秒程度のヒットは通常は無関係なので、コードをクリーンに保つためにそれらを使用する傾向があります。

于 2009-07-10T15:20:49.797 に答える
1

あなたの例のロジックに同意しますが、例外処理ブロックとプログラムテストでどの例外を処理していると思いますか? あなたの例外処理ブロックは本当に「何かが起こった場合に備えて」だと思います。したがって、実際には例外処理規則に帰着します。

例外を処理する必要がなく、明確なアーキテクチャ境界を越えていない場合は、処理しないでください。コンポーネント境界の端にある場合は、それをラップして、オリジナルを内側の例外に配置します。

機能がコードから呼び出されていた場合は、応答などのステータス表現で結果をテストするか (HRESULT はその代表的な例です。0 == 成功、!= 0 == 失敗)、または例外を使用します。

プログラム エラーやコンポーネント エラーのテストでは、例外を使用します。UI でユーザーからの入力を検証する場合は、単純にロジックを使用してステータス コードを返し、エラーをユーザーに伝えることができます。

最後に、ローカリゼーションについても考えてみましょう。システムに英語のエラー メッセージを波及させてフランス語を話すユーザーに表示しても役に立たず、フランス語版を生成するために UI で文字列の解析を開始したくない場合は、例外を使用する方法です。例外のペイロードに、ユーザーが修正アクションを実行するための有用なエラー メッセージを生成するのに十分な情報が含まれている限り、問題はありません。

コンポーネント間に密接な結合があり、呼び出し元のコンポーネントがさまざまなステータス条件で何をすべきかを知っている場合は、ステータス コードを使用します。

ところで、ToString() を使用してメッセージだけでなく、スタック トレースもログに記録すると、問題を解決するためのより役立つ情報が得られます。

HTH

于 2009-07-10T15:27:23.857 に答える
0

その場合、あなたの場合はエラーを適切に処理しているので、実際にはtry/catchは不要だと思います

しかし、一番下のものは、私が信じているスタイルは、より複雑な状況に使用する必要があります

于 2009-07-10T15:10:16.227 に答える