43

これは、別の質問として尋ねることをお勧めした列挙型の未処理のケースに関する他の質問の別のケースです。

SomeEnum次のように処理するswitchステートメントがあるとします。

enum SomeEnum
{
  One,
  Two
}

void someFunc()
{
  SomeEnum value = someOtherFunc();
  switch(value)
  {
     case One:
       ... break;
     case Two:
       ... break;
     default:
         throw new ??????Exception("Unhandled value: " + value.ToString());    
  }
}

ご覧のとおり、可能なすべての列挙値を処理しますが、新しいメンバーが追加された場合に備えてデフォルトで例外をスローし続け、処理の欠落を認識していることを確認します。

私の質問は、指定されたコードパスが処理/実装されていない、またはアクセスされるべきではないことを通知したい場合の正しい例外は何ですか?以前は使用しNotImplementedExceptionていましたが、適切ではないようです。次の候補はですInvalidOperationExceptionが、その用語は正しく聞こえません。正しいものとその理由は何ですか?

4

11 に答える 11

38

個人的には、プロジェクトにカスタム例外を追加します。

public class UnexpectedEnumValueException<T> : Exception
{
    public UnexpectedEnumValueException( T value )
        : base( "Value " + value + " of enum " + typeof( T ).Name + " is not supported" )
    {
    }
}

その後、必要に応じて使用できます。

enum SomeEnum
{
  One,
  Two
}

void someFunc()
{
  SomeEnum value = someOtherFunc();
  switch(value)
  {
   case SomeEnum.One:
    ... break;
   case SomeEnum.Two:
    ... break;
   default:
      throw new UnexpectedEnumValueException<SomeEnum>(value);    
  }
}

そうすれば、たとえば SomeEnum に新しい値を追加するときに、「UnexpectedEnumValueException<SomeEnum>」を検索して、変更によって影響を受ける可能性のあるすべての場所を見つけることができます。エラー メッセージは、一般的な例外よりもはるかに明確です。

于 2014-07-15T15:54:37.633 に答える
31

失敗する(無効なものを生成する)内部操作であるInvalidOperationExceptionため、進むべき道です。

ドキュメントは単に言う:

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

オブジェクトの現在の状態が の無効な戻り値につながるため、これはおおむね適切です。したがって、そもそもsomeOtherFuncの呼び出しを避けるべきでした。someFunc

于 2012-11-30T12:30:45.417 に答える
26

InvalidEnumArgumentException クラスを使用してみてください

void someFunc()
{
  SomeEnum value = someOtherFunc();
  switch(value)
  {
     case One:
       ... break;
     case Two:
       ... break;
     default:
          throw new InvalidEnumArgumentException(); 
  }
}
于 2012-11-30T12:25:34.263 に答える
11

列挙型が表すセマンティクスに依存すると思います。

オブジェクトの状態を表す場合は、InvalidOperationExceptionが適切です。

サポートされていないアプリケーション機能を表す場合は、NotSupportedExceptionが適切です。

NotImplementedExceptionは、現在実装されていないが、将来のバージョンで実装される可能性があるアプリケーション機能に適しています。

...

于 2012-11-30T12:30:12.050 に答える
5

switch ケースの ReSharper 命題:

switch(parameter)
{
   default:
      throw new ArgumentOutOfRangeException("parameter");
}

ただし、ニーズに合わない場合は、この関数で実行される内容に関するカスタム例外タイプを定義できます: SomeEnumOutOfRangeException...

于 2012-11-30T12:30:35.790 に答える
2

新しい値が追加され、どこかでそれを処理するのを忘れた場合、それはプログラミング エラーか、Eric Lippert が呼ぶBoneheaded Exceptionです。BoneheadedException適切な FCL 例外タイプがないプログラミング エラーを検出するたびにスローする独自のクラスを作成します。

于 2012-11-30T12:37:39.420 に答える
1

この状況で私がしようとしているのは、switchステートメントの代わりに辞書を使用することです。(一般に、このようなマッピングは辞書によってより適切に定義されますswitch。このようなマッピングを整理するためのより良い方法が常に、またはほとんど常に存在するため、ステートメントは自動的にコードの匂いになると私はほとんど考えています。)

ディクショナリを使用する場合、説明されていない値でディクショナリのインデックスを作成しようとすると、 が返され、KeyNotFoundException「デフォルトの場合はどうすればよいですか?」と尋ねる理由はなくなります。 .

于 2017-04-12T21:06:03.910 に答える
-1

この状況は実際にはコントラクトの失敗であり、必ずしも列挙型に固有のものではありません。コード コントラクトを使用できない場合は、独自の例外の種類を作成してスローできます。

case One:
   ... break;
 case Two:
   ... break;
 default:
    throw new ContractViolationException("Invalid enum");
于 2012-11-30T12:33:58.450 に答える
-2

実装されていない列挙値に対して例外をスローしているため、 NotImplementedException と言います。

于 2012-11-30T13:03:20.127 に答える