2009-04-09 13 views
12

の派生コンストラクタを実行するここで問題となるのは、派生クラスにオブジェクトを渡したいのですが、ベースクラスが直ちに派生クラスを呼び出すため、そのオブジェクトを使用するクラスのStart()メソッドです。基本コンストラクタの前にC#

ここでは、基本クラスの抜粋(便宜上、BarcodeScannerに改名)です。

public abstract class MyBase 
{  
    public MyBase() 
    { 
     if (Initialize()) 
      this.Start(); 
    } 

    public abstract bool Initialize(); 
    public abstract void Start(); 
} 

私が作成している派生クラスは次のとおりです。

class MyDerived : MyBase 
{ 
    private string sampleObject; 

    public MyDerived (string initObject) 
    { 
     sampleObject = initObject; 
    } 

    public override bool Initialize() 
    { 
     return GetDevice(); 
    } 
    public override void Start() 
    { 
     Console.WriteLine("Processing " + sampleObject.ToString()); 
    } 
} 

基本コンストラクタの前に派生したコンストラクタをC#で実行させることはできません。オブジェクトを使用する前に派生クラスにオブジェクトを渡すためのソリューションを探しています。

MyDerivedコンストラクタの中にInitialize/Start ifブロックを置いて、この問題を回避しました。しかし、基底クラスから派生する他のクラスがあります。私は、この派生クラスごとにInitialize/Startコードブロックを繰り返す必要がありました。私はベースクラスを変更する代わりに参照したいと思います。

答えて

15

あなたがしようとしていることは、C#では不可能です。基本クラスのコンストラクタは、派生クラスのコンストラクタの前に実行する必要があります。それ以外の場合は、オブジェクトの破損の可能性があります。子オブジェクトは、その基底が完全に構築され利用可能であると想定できる必要があります。

+2

さて、空のオーバーライドInitialize/Startメソッドを作成し、それらのコードをderivedInitialize/derivedStartメソッドに移動し、派生コンストラクタでif(derivedInitialize())derivedStart()を呼び出してください。洗練されたソリューションはないかもしれませんが、まだ他の方法があります。 – James

+0

フレームワークが不完全に構築されたオブジェクトのエクスポーズを防止しようとすることはしばしば良いことですが、クラスがそのようなオブジェクトにアクセスすることがより有用な場合があります。部分的に構成されたオブジェクトを使用します。例えば、クラスが自身のライフタイムと一致する 'IDisposable'オブジェクトをカプセル化する場合は、フィールドイニシャライザを使用して設定すると便利です。 C#で悲しいことに、安全にそれを行うためのきれいな方法はありません。基本クラスのコンストラクタがスローすると、処分が必要なものへの参照を取得することはできません。 – supercat

17

IMHOあなたのデザインは間違っています。コンストラクタ内からプロセスを開始しないでください。消費コードは、必要に応じて明示的にStart()メソッドを呼び出す必要があります。

+0

+1 "Start()"の呼び出しのために。 –

+0

+1。この男は正しいです、あなたは必要です。()/ .Initialise()。コンストラクタで仮想メソッドを呼び出さないでください。 – Quibblesome

+0

+1。 C++は、コンストラクタからの理由で仮想呼び出しを制限します。 –

0

Initialize(そして、おそらくStart() - 私は通常、これがユーザによって呼び出されたパブリックメソッドであるが)を構築した後に呼び出すようにデザインを修正するだろう。

BarcodeScannerを作成している場合は、最初にスキャンするときにこれを行うことができます。派生クラスのデータを使用してメンバーを怠惰に初期化するだけです。

これは問題を回避し、ユーザーからの実際の使用状況を変更することはありません。

+0

スキャンはデバイスによって非同期に開始されるため、スキャン開始に基づいて初期化することはできません。後見では、MicrosoftはStart()メソッドの名前をReady()メソッドに変更する必要がありました。 Start()メソッドはスキャナーのみを読み込みますが、実際にはスキャンを開始しません。 – James

関連する問題