2009-05-29 11 views
7

イベントはメソッドのようなものですが、戻り値の型や空白がないのですか?イベントに.NETの戻り値の型がないのはなぜですか?

私は知りたいのですが、なぜそうですか?なぜ型を返さないのですか?

+1

イベントハンドラ*値を返すことができます。http://stackoverflow.com/a/3325424/119271を参照してください。 – Douglas

答えて

22

イベントは複数のリスナーで処理できるため、イベントハンドラへの順序は保証されていません(実際にはサブスクライブされている順番でコールされているとは思いますが)。

代わりに、データを返すイベントの場合、キャンセルプロパティをtrueに設定できるCancelEventArgsなどの変更可能なEventArgsオブジェクト。戻り値に対するこれの利点は、チェーン内のイベントハンドラがプロパティを見て、別のハンドラがすでにそれを設定しているかどうかを確認できることです。しかし、あなたはまだ財産を設定する最後のものが勝つ状況で終わります。

戻り値だった場合、全体のコンセプトはもっと複雑になります。

+0

複数のイベントハンドラは、すべての非同期リターンがどこから来たのかを判断することで確かに面倒です。 – ChrisBD

+0

+1;いい答えだ。 –

+0

@ChrisBD - 個々のハンドラからのフィードバックを得るプロセスは明確に定義されています。あなたが変更可能な "args"型を使用するときとまったく異なるわけではありません。 –

3

これらは必要ありません。それについて考える。彼らは何を返すだろうか?

+0

+1まさに私が書くつもりだった。彼らは何を返すだろう、彼らはそれを何を返すのだろうか、そしてそれで何ができるだろうか? –

+0

...そして特に。誰がそれを返すでしょうか? –

+0

実際には、イベントを「返す」のは非常に便利です。たとえば、AppDomainクラスのAssemblyResolveイベントを使用すると、アセンブリを動的に読み込んでAppDomainに返すことができます。問題は.NETが戻り値の代わりに可変EventArgsパラメータを使用することを選択した理由です。 – Josh

-2

これは、イベントが非同期呼び出しであるためです。同じイベントの複数のコピーを同時に処理させることができます。

したがって、イベントライザーが同期してイベントハンドラが完了するまで待機する必要がある戻り値の型を処理するための情報だけを渡します。これは他の手続き呼び出しと同じようになります。

+0

イベントハンドラは、順序は未定義ですが、同期して順番に呼び出されます。もしそうでなければ、すべての地獄は緩んでしまうだろう。 – Josh

+0

私はそれが本当だとは思わない。イベントハンドラは、イベントが同期的に発生したスレッドで実行されると思います。 –

+0

おそらく私は私が持っているべきであるように自分自身を明確に説明しなかったでしょう。 私が意味していたのは、イベントの発生を、それを処理するコードによって事前に決定することができないということでした。ハンドリングコードはイベントライザーと同じスレッド上にある必要はなく、ハンドラーが完了するのを待つようにイベントを発生させるコードは必要ありません。可変タイプ。 – ChrisBD

0

イベントを発生させることは、一方通行の信号です。彼らはイベントのライザーが消費者に依存しないため、ほとんどが疎結合を達成するために使用されます。戻り値は、コンシューマに依存関係を作成します。

+0

私はそれが良い考えではないことに同意している間に - 私はそれが片方向ではないことに同意しない。 Invoke(最も一般的に使用される方法)は同期的であり、フィードバックを受け入れることは非常に一般的です(「args」、たとえばCancelEventArgs)。戻り型のパブリッシュは、変更可能なargsとあまり変わらないので、追加の依存関係は作成されません。 –

+0

私は、C#evenst(つまり、ツーリング)がイベントコンシューマーからのフィードバックを可能にするという点を見ていますが、イベントのコンセプトは依然として一方向の通知であり、CancelEventArgsのようなメカニズムは概念のハックです。 – Vizu

8

実際には、イベントにはに戻り値があります。単純に、複数のリスナーが存在する場合、より複雑な処理を必要とするため、良い考えではありません...もっと一般的には、サブクラスEventArgsの設定可能なプロパティがあるかもしれません。

ただし、イベントでの戻り値の使用例を次に示します。これはではなく、です。参考情報のみ:

using System; 
delegate int SomeBizarreEvent(object sender); // non-standard signature 
class Foo { 
    public event SomeBizarreEvent Bizarro;  
    public void TestOverall() { 
     SomeBizarreEvent handler = Bizarro; 
     if (handler != null) { 
      Console.WriteLine(handler(this)); 
     } 
    } 
    public void TestIndividual() { 
     SomeBizarreEvent handler = Bizarro; 
     if (handler != null) { 
      foreach (SomeBizarreEvent child in handler.GetInvocationList()) { 
       Console.WriteLine(child(this)); 
      } 
     } 
    } 
} 
class Program { 
    static void Main() { 
     Foo foo = new Foo(); 
     foo.Bizarro += delegate { return 1; }; 
     foo.Bizarro += delegate { return 5; }; 
     // writes 5 (the last result wins) 
     foo.TestOverall(); 
     // writes 1, 5 
     foo.TestIndividual(); 
    } 
} 
+0

素晴らしい点。私は実際にそれを忘れてしまった(私の答えでは言ったが)、戻り値が使用されないということは慣例によるものだということだけである。 – Josh

0

これはイベントシステムの設計に含まれています...イベントシステムの主な目的は通知ではないことです。

イベントは、リスナー(オブザーバー)に重要なアクションが発生したことを通知する方法です。これは、重要なアクションが発生したことをリスナーに通知するだけでなく、それが何であるかをソースに認識させるような方法で設計されていません。扱われている???そうでなければ...あなたは何をするか決定する方法???

イベントが、ハンドラが関連付けられていない場合に返される値を返す必要がある場合。イベントに複数のハンドラがある場合はどうなるのですか?次に、返されるハンドラ値を決定する方法。

これらのイベントはすべて、値を返すことができます。それはベストプラクティスではありませんが。

+0

多くのイベントがフィードバックループを提供します。最も一般的な例はCancelEventArgsです。 return-valueとmutable-argsにかかわらず、個々のハンドラから結果を検査する仕組みは明確に定義されています。 –

+0

私は "イベントシステムの主な目的は通知ではありません"と言った... ...それはできないと言わなかった.. しかし、いくつかのケースについて言及したように、イベントはユーザーからのフィードバック... CancelEventArgsのように....しかし、これは必要なケースではありません。 Event Raisingスレッドは、フィードバックがコンシューマから到着するまで状態を保存するか、呼び出しをブロックする場合にフリーズする必要があることを知っています。これにより、複雑さが増します。 –

+0

Observable上のオブザーバを登録すると、オブザーバブルオブザーバにオブザーバを登録すると、オブザーバに、オブザーバの登録メソッドを呼び出す特定のトリガについて通知または通知する必要があるとき... 再び観察者パターンの主要な目標は、消費者に特定のトリガについて通知することであり、観察者のフィードバックを取る必要はない。 この場合、オブザーバに通知するブロッキング呼び出しを行うか、または通知を処理するための新しいスレッドを作成します。 –

関連する問題