5

私はこれについて私が言いたいことを知っていると思いますが、よくわかりません...

フレームワークのドキュメントでは、型を次のように要約しています。

メソッド呼び出しがオブジェクトの現在の状態に対して無効である場合にスローされる例外。

明確なケースがあり、思いつくのは、操作でデータベースを開く必要があるが、データベースに接続するために必要な情報でオブジェクトが初期化されていない場合です。

(接線: 一方、接続を明示的に開くことも要求する ADO.NET の動作は明確ではありません。DataAdapter は、単に接続を代わりに開き、接続が閉じられた場合にのみ再度閉じることによって、これから逸脱します。エントリ, そして私はこれが便利だと思い、すべてのためにこのパターンを使用するADO.NETラッパーを自分自身にしました. もちろん、これは2つのExecuteNonQueryを実行し、その間に不必要にプールへの接続を返すリスクがあることを意味します, しかし、私はまだ開いたり閉じたりすることができます私が望むときに接続し、このパフォーマンスの低下は、例外を取得することに比べれば何もありません.)

私の質問に対する答えは、そのような明確な状況でのみ例外をスローする必要があるということだと思います。ただし、次のシナリオでは、どの例外の種類が最も適切でしょうか。

public class FormatterMapping
{
  Dictionary formattersByName = new ...();

  public IFormatter GetFormatter(string key) 
  {
     IFormatter f;
     if (formattersByName.TryGetValue(key, out f)) 
       return f;
     else
       throw new ??Exception("explanation of why this failed.");
  }
}

私の最初の本能は、ArgumentException をスローすることでした。それから、引数が「間違っている」のと同じように、マッピングにキーが欠落している可能性があると考え始めました。X がマッピングに含まれていないため、基本的に「Get formatter X」操作は無効ですが、X が「そこにあるはずだった」のか、ここで X を要求するのが賢明ではないのか、私にはまったくわかりません。

もちろん、null を返すことで問題全体を回避することもできますが、それはより大きく、より深いワームの缶を開きます。戻り値がいつ使用されるかを知る方法がないため、NullReferenceException で後で爆発するコードは、問題が発生した場所と明確な関係を持っていない可能性があります。マッピングが正しく設定されていないか、それを使用するコードが要求してはならないものを要求したかのいずれかです。

この問題を回避する別の方法は、TryGetFormatter オプションを使用することですが、これを使用する方法は、呼び出し元がマッピングに含まれるものと含まれないものを実際に認識しているため、ユーザー コードにこのパターンを強制することはできません。どちらでもいいです。

答えないでください。ApplicationException をスローする必要があります。そして、コードが何をすべきだと思うかについて、その理由を提供してください。結局のところ、ここで本当に問題になっているのは推論です。

誰かが私を別の方法で説得するまで、私は ArgumentException に傾いています。マッピングの観点からは、この議論は間違っているので、少なくともこれを裏付ける明確な理由が 1 つあります。:)

4

2 に答える 2

4

ArgumentException代わりに、次のようなものに使用することを検討します。

if (string.IsNullOrEmpty(key))
{
    throw new ArgumentException("Expected a key");
}

あなたの例では、InvalidOperationExceptionまたはKeyNotFoundExceptionが適していると思います。または、適切だと思う場合は、自分で書いてください。

私の意見は純粋主義者には好まれないかもしれませんが、私の例外は私が働いているシステムで自動的にメールで送られてくるので、最終的にほとんどの場合、十分な有用な情報を得ることができる限り、キャッチした例外の種類は気にしません。何が起こったのかを確認します。これも:

  1. 分かりやすいエラーメッセージ
  2. スタック トレース
  3. 必要な場合は内部例外
  4. 追加のコンテキスト情報は、オプションのボーナスになります。つまり、例外がスローされた前後の値を取得できれば、デバッグがはるかに簡単になります。
于 2012-02-27T16:54:43.187 に答える
4

どちらも完璧ではなく、どちらでも問題ありません。または、本当に明確なものが必要な場合もあります。

KeyNotFoundException

public class FormatterMapping
{
    Dictionary<string, IFormatter> formattersByName = new ...();

    public IFormatter GetFormatter(string key) 
    {
        // validate the argument
        if (!formattersByName.ContainsKey(key))
            throw new KeyNotFoundException("No formatter exists for given key");

        return formattersByName[key];
    }
}

または、 Dictionary<> にスローさせることもできます。

1 つを選択して文書化し、先に進むことをお勧めします。通常、スローする特定の例外を選択するために多くの時間を無駄にする価値はありません。動作を文書化することはより重要です。

于 2012-02-27T16:25:53.373 に答える