2017-10-02 14 views
3

次のコードでは「Hello、World!」と表示されないのはなぜですか?C#イベントを他のイベントに直接サブスクライブできない理由

using System; 

namespace Test 
{ 
    public class Program 
    { 
     public static void Main(string[] args) 
     { 
      var a = new A(); 
      var b = new B(a); 
      b.Evnt += val => Console.WriteLine(val); 
      a.Do(); 
     } 
    } 

    public class A 
    { 
     public void Do() 
     { 
      Evnt("Hello, World!"); 
     } 

     public event Action<string> Evnt = v => {}; 
    } 

    public class B 
    { 

     public B(A a) 
     { 
      a.Evnt += Evnt; // this does not work 
     } 

     public event Action<string> Evnt = v => {}; 

    } 
} 

しかし、私は

a.Evnt += v => Evnt(v); 

すべてが正常に動作してライン

a.Evnt += Evnt; 

を交換する場合。

これは禁止されている場合、あるイベントを別のイベントにサブスクライブする意味と、そのときにコンパイルエラーまたは警告が表示されないのはなぜですか?

答えて

5

それは、このコードを印刷「2」と同じ理由で失敗した:ここで

int x = 2; 
int y = x; 

Action a =() => Console.WriteLine(y); 

x = 3; 
a(); 

、あなたのイベントハンドラが割り当て時のa.Evntの値である - でEvntのために持っているものは何でもaは、あなたがBがイベントハンドラのために取得するのは、BBのコンストラクタにaを渡すときです。

public B(A a) 
{ 
    a.Evnt += Evnt; // this does not work 
} 

実際にはうまくいきます。それはあなたが違う何かをするように言っていると思っただけです。

ここでは、ハンドラが実行されたときにいつでもEvntを評価するハンドラがあります。したがって、この場合、a.Evntがその間に変更された場合は、新しい値a.Evntの出力が表示されます。

public B(A a) 
{ 
    a.Evnt += v => Evnt(v); 
} 

書き換えBのように、あなたが鮮明な画像を得ることができます:

public class B 
{ 

    public B(A a) 
    { 
     a.Evnt += Evnt; // this does not work 
    } 

    public event Action<string> Evnt = v => { Console.WriteLine("Original"); }; 

} 

あなたの質問のタイトルがうまく言葉で表現されていません。あなたはイベントを割り当てていない、あなたはイベントハンドラを割り当てている。また、「これは機能しません」は、問題を説明するのに便利な方法ではありません。物事は働かない無限の方法があります。私の最初の前提は、あなたのコードがコンパイルされないということでした。次回は、あなたが見たいと思った行動、そしてあなたが実際に見たものを説明してください。コンパイルに失敗したかどうか、または実行時に例外を投げたかどうかを言ってください。まったく予想外のことが起こっただけです。エラーメッセージまたは例外メッセージがある場合は、メッセージのテキストを入力します。

0

lambdaは呼び出し時に評価してキャプチャするため、+ =を一度付けてからref(評価なし)を呼び出します

関連する問題