2011-12-16 7 views
1

私は外部デバイスと通信するソフトウェアに取り組んでいます。デバイスには、初期化値のセット(calibrationData)が必要です。これらのキャリブレーションデータは、この機器の部品ごとに異なります。最初のバージョンでは、較正データをユーザが選択することができ、したがって、ユーザは、偶然、異なる部分で得られた較正データをロードすることができる。デバイスは機能しますが、正しく測定されません。 私はデバイスに接続されているよ前にIDをチェックすることはできませんよコンストラクタの最後にスロー例外がオブジェクトにダメージを与えますか?

public Instrument(CalibrationData calibration) 
    { 
     _camera = new Camera(); 
     _driver = new Driver(); 

     if (_camera.GetUniqueId() != calibration.GetCameraUniqueId()) 
      throw new WrongCalibrationException("Calibration file was obtained on different equipment."); 
     //Don't write anything here. Exception has to be the last code in the constructor. 
    } 

、その後、どこか他の

try 
{ 
    instrument = new Instrument(calibration); 
} 
catch (WrongCalibrationException e) 
{ 
    MessageBox.Show("You tried to load calibration obtained on different device."); 
} 

を持っています。

この質問は2つのうち実際に含まれています。

  1. 私の解決策は正しいですか?私は適切なキャリブレーションの使用を自動的にテストし、プログラマに依存しないで別のメソッド(Instrument.AreYouProperlyCalibrated()のようなもの)を呼び出すために私のコードを使用します。

  2. 例外が最後にスローされたときコンストラクタの?私はちょっと頭がおかしくなっています。建設業者が完成した後、C#がいくらか不安を抱いていて、ctorが例外を投げた場合にこれが異なるかもしれないということです。

おかげ

+0

MarcとYuriyはかなり私が思うすべてをカバーしています。私はちょうどあなたがクラスのために持っているファイナライザはコンストラクタが完全に完了していないにもかかわらず実行されますので、ファイナライザ(それはとにかく持っているように見えない)でそれを認識しても追加することを追加します。 –

答えて

3

インスタンスすでに完全には(実際に、あなたも完全にすべてのコンストラクタをバイパスし、まだ有効なインスタンスを取得することができます)が存在する - それだけで実行されなかった任意の初期化コードが実行されていないことを意味します。例えば

それは良いアイデアではありませんが、あなたは

_camera.HereIsMe(this); 

または

SomeExternalObject.Track(this); 

すなわち、コンストラクタ中にタイプのからオブジェクトインスタンスを渡すことができます何もない実行時には、このオブジェクトは通常のように存在し、適切に処理されなければならないので、ひどいことになります。しかし、いくつかのケースでは工場を使用するクリーナーです:

public static YourType Create(args) { 
    // TODO: perform enough work to validate 
    return new YourType(validated args); 
} 

しかし、繰り返しになります。 問題がある場合、コンストラクターからスローすることは予期しないことではなく、有害ではありません。

+0

問題のオブジェクトがIDisposableを実装している場合、 'protected'コンストラクタからインスタンスを渡す(ファクトリメソッドで利用できるようにする)ことは非常に良いアイデアです。コンストラクタをラップするファクトリメソッドは、部分的に構築されたオブジェクトに対してDisposeを呼び出すことができます。もちろん、この可能性を処理するためにDisposeルーチンを記述する必要がありますが、派生クラスの場合、すべてのコンストラクタに 'try'ブロックを入れるよりもきれいに見えます。 – supercat

2

それは好みの問題です。たとえば、DateTimeは、constructorに例外をスローします。むしろそうでない場合は、Build(Calibration calibration)のような静的メソッドを使用できます。良い例は、XMLコメントを使用して、タイプのユーザーにコンストラクタが例外をスローすることを<exception>タグで知らせることです。コンストラクタが始まる前に

2

コード内のどこからでも例外をスローすることができます。

コンストラクタがどこかにスローされてスローが発生した場合、オブジェクトは作成されません。あるいは、より正確に作成されますが、コード実行フローは例外に従います。オブジェクトが作成されていたコードブランチ内にあるので、それはあなたに関係することについて全く作成されていなかったようです。

あなたが投稿したコードだけを考えてあなたのアプローチはOKです。明らかに、CameraDriverのコンストラクタ(削除されていないものなど)にある可能性のあるものに関連する他の問題があるかもしれませんが、それは別の問題です。

0

私はカメラとドライバオブジェクトが取得する必要があることを指摘BY MARCの答えに追加したいと思いますクラスに注入されます。 implementing Dependency Injection in C#

この(1件のうちの1つ)記事を参照してください。私はこの意見で騙されないことを願っています。 ;)

関連する問題