2011-01-29 10 views
1

C#では、イベント関数に戻り値を設定できます。ただし、最後のイベントの戻り値のみを受け取ります。また、以前のイベントの戻り値を取得する方法がないようです。C#のイベントのベストプラクティス

いくつかの良い方法はありますか?私はいつもvoidを使うべきですか?私の限られた経験から、値をチェーンしたい場合はrefを使用する必要がありますか?

イベントの書き込み方法を教えてください。私はFunc < ref t、return T>を使いたかったが、refはそこでは違法であり、私は行動が同じであると想像している。 (私は以下で終わりました)。 refを使用する場合、イベントを2行ではなく1行にする方法はありますか?

delegate int FuncType(ref int a); 
    static event FuncType evt; 
    static void Main(string[] args) 
    { 
     evt += foo; 
     var aa = 1; 
     var a = evt(ref aa); 
     evt += bar; 
     var bb = 1; 
     var b = evt(ref bb); 
    } 

    static int foo(ref int a) 
    { 
     a = a*3; 
     return a; 
    } 

    static int bar(ref int a) 
    { 
     a=a +1; 
     return a; 
    } 
+2

あなたは何をしようとしていますか?それがあなたのニーズに合った答えを与えるのに役立つことが分かっています。 – Oded

+0

上記のコード例では、イベントを使用するのが難しいようです。たぶんあなたはあなたの問題を解決するために別の方向を見ているべきです。 –

+0

@Andreas Vendel:正確には、私は実際にwinformsのイベントを使用して、私は周りに遊ぶことに決めた、それは非常に有用な外観didnt。だから私は正しく、きれいにそれを使用する方法を見つけようとしました –

答えて

2

イベントに複数のサブスクライバがある場合に戻り値を取得する場合は、Delegate.GetInvocationListを使用します。次に、

foreach(FuncType d in evt.GetInvocationList()) { 
    int value = d(parameter); 
    // do something with value 
} 

と言うことができますが、一般的に、イベントハンドラでは戻り値を避けることをお勧めします。

3

Event DesignのMicrosoftのドキュメントをご覧ください。

8

このように、GetInvocationListを使用すると、それぞれのメソッドを個別に呼び出して、返されたデータを処理することができます。

ただし、その前にEventHandler<T>EventArgsを使用してください。

すべて」の返品をにする必要があります。

public class BalanceChangedEventArgs : EventArgs 
{ 
    public readonly double OldBalance; 
    public readonly double NewBalance; 

    public BalanceChangedEventArgs(double oldB, double newB) 
    { 
     OldBalance = oldB; 
     NewBalance = newB; 
    } 
} 

public class Account 
{ 
    private double balance; 

    public EventHandler<BalanceChangedEventArgs> balanceChanged; 

    protected void OnBalanceChanged(BalanceChangedEventArgs eArgs) 
    { 
     if (balanceChanged != null) 
      balanceChanged(this, eArgs); 
    } 

    public double Balance 
    { 
     get { return balance; } 
     set 
     { 
      if (balance == value) 
       return; 

      OnBalanceChanged(new BalanceChangedEventArgs(balance, value)); 

      balance = value; 
     } 
    } 
} 
2

「ベスト・プラクティス」は唯一voidのEventHandlerを使用することです:このサンプルコードを確認してください 。正確には、最終価値のみの問題のためです。

結果を結合する場合は、適切なプロパティを持つEventArgsの子孫を定義します。リストや合計値などを使用します。

7

「イベント」と「コールバック」を混同しないでください。カスタマイズのための「フック」を提供する場合は、次のいずれかを考慮してください。

  • フックの仮想メソッドを持つ基本クラス。
  • コンストラクタに渡される、またはプロパティを介してアクセスされるコールバックオブジェクトのインターフェイス。
  • デリゲートは、コンストラクタに渡されるか、プロパティを介してアクセスされます。

あなたは上記と考え、まだイベントを使用したいしている場合、あなたはあなたのイベントの引数の型、例えば、e.Resultまたはe.Handledの一環として、「結果」が含まれる可能性が。複数のイベントハンドラが互いに値を上書きする可能性があるので、他の回答が示唆しているように呼び出しリストを反復して組み合わせる必要があります。すべての結果を照合するか、e.Handledに使用されているような「早期終了」戦略を立ててください。

+0

イベントリストを手作業で呼び出すことなく*イベントを変更する際の問題は、それはワンショットの取り決めです:後のハンドラは、以前のハンドラの値を検出できない形で変更する可能性があります。差別化のための+1と示唆された代替アプローチ。 –

+0

@pst:true。あなたのコメントを反映するように編集します。 –

関連する問題