C#でカスタム例外を作成するタイミング


9

COMポートを介して単純なハードウェアデバイスとインターフェイスするクラスを作成しています。デバイスはさまざまなモードを使用するように構成できるため、私のクラスにはタイプSetOperatingModeを取り込む関数があります。次のようになります。enumUsbDeviceMode

class UsbDevice
{
    public void SetOperatingMode(UsbDeviceMode mode)
    { 
     byte[] buffer = new byte[4];
     buffer[0] = 0x5A;
     buffer[1] = 0x02;
     buffer[2] = (byte)mode;
     buffer[3] = 0x00; //IO_TYPE is always 0 in this case.

     _port.Write(buffer, 0, 4);
     int read = _port.Read(buffer, 0, 2);
     bool successfulSet = (read == 2 && buffer[0] == 0xFF && buffer[1] == 0x00);
    }
}

enum UsbDeviceMode
{
  IO_MODE = 0x00,
  IO_CHANGE = 0x10,
  I2C_S_20KHZ = 0x20,
  I2C_S_50KHZ = 0x30,
  I2C_S_100KHZ = 0x40,
  I2C_S_400KHZ = 0x50,
  I2C_H_100KHZ = 0x60,
  I2C_H_400KHZ = 0x70,
  I2C_H_1000KHZ = 0x80,
  SPI_MODE = 0x90,
  SERIAL = 0x01
};

いくつかの理由により、この操作が失敗する可能性があります。COMポートが存在しなくなった、デバイスがロックされたか失敗した、または何らかの理由で操作が失敗した可能性があります。

失敗は予想外ですが、珍しいことではありません。障害の二つの異なるモードがあります:COMポートは、(例外をスローTimeoutExceptionし、InvalidOperationException期待されるものです)。または、デバイスの障害インジケータを読み返すこともできます。

場合はいずれの場合も、SetOperatingMode()失敗した場合、デバイスや通信が何らかの形で壊れている、このクラスはそれについて何もすることはできません。

2つの質問があります。

  1. InvalidOperationExceptionポートが閉じている場合は、「事前スロー」する必要がありますか?MSDNのドキュメントから、SerialPort.WriteおよびSerialPortポートが閉じている場合、読み取りがスローされます。関数の一番上でそれを確認することもできますし、_port.Write()投げるだけでもかまいません。
  2. ときにスローされる全く新しい例外タイプがあるはずsuccessfulSetですかfalse?場合successfulSetfalse、このクラスはに行うことができます何もありません。SetOperatingModeFailedExceptionCOMポートの障害とデバイスの障害を区別するために、何らかの例外が必要ですか?この1つのスポットのためだけに例外クラス全体を作成するのは、かなり時間がかかるようです。

回答:


10

ユーザーが特定のエラー状態をプログラムで区別できるようにする場合は、カスタム例外を使用します。 そのような状況が存在しない場合は、より「一般的な」例外をスローし、カスタム例外クラスの作成を回避できます。

SetOperatingMode()例の特定のケースでは、このメソッドの呼び出しが失敗する可能性がある特定の方法を呼び出す必要がない限り、より一般的な例外を使用する方がよいでしょう。つまり、SetOperatingModeFailedExceptionを呼び出した結果として例外をスローするつもりであるSetOperatingMode()が、発生したオペレーティングモードの障害の種類をプログラムで区別しない場合は、カスタム例外の作成を省略できます(それが唯一の例外であるため) thrown)、そして単にをスローしInvalidOperationExceptionます。これはおそらく最も近い既存の例外です。

それでもカスタム例外を作成する場合は、などのさまざまなメソッドで再利用可能な例外を作成しますOperationFailedException


2

クラスの作成は簡単です。時間のかかるプロセスではありません。問題を隠すコードのデバッグは困難です。そして時間がかかる。

例外を作成するかどうかを決めるとき、「この動作は正常であるか、予想される動作であるか、またはこの動作は例外的であるか」と自問する必要があります。

この場合、予期される動作は、動作モードが常に設定されていることです。したがって、例外をスローする必要があることをお勧めします。書き込み操作のバブルアップからの例外を許可します。最後の行でエラーが発生したことが判明した場合は、SetOperatingModeFailedExceptionも作成します。

この場合、あなたのメソッドは実際には動作モードを設定しようとする責任しかありません。接続を管理する責任はありません。それは他の誰かの責任であり、それが適切に行われなかった場合、例外がスローされるべきです。


あなたは彼の質問を誤解しているようです。彼は既存の例外タイプの1つを使用するべきですか、それとも自分自身をロールすべきですか?
Robert Harvey

1
実際、私は彼の質問に答えました。「私は、書き込み操作のバブルからの例外を許可します。」(つまり、ポートが開いているかどうかを確認する必要はありません)、「SetOperatingModeFailedExceptionを作成します」。
Stephen

1
ふff。カスタム例外は必要ありません。選択したものを除いて、メソッドがスローする他の例外は何ですか?SetOperatingModeFailedExceptionは、たとえばInvalidOperationExceptionを超える値をどのように追加しますか?どちらの例外も、失敗が発生した理由を知らせたり、スローされた例外のタイプに基づいてプログラムで応答する方法提供したりしません また、新しい例外クラスを作成するのに費用はかかりません
Robert Harvey

1
それはどんな価値を追加しますか?適切に文書化すると、多くの価値が追加されます。この特定の問題が発生したことを示しています。呼び出し元のコードがこのエラーから回復できないことは明らかではありません。
Stephen

スローした例外に詳細なエラーメッセージを提供できます。特定の例外を使用して呼び出し元にプログラムによる制御を提供する予定がない限り、カスタム例外を作成することは時間の無駄だと思います。「ユーザーがいくつかのエラー状態をプログラムで区別できるようにしたい場合は、独自のユーザー定義の例外を作成してください」と書かれているこのことを読んでください。
Robert Harvey
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.