为什么以下代码无法打印" Hello,World!"?
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 += Evnt;
与
a.Evnt += v => Evnt(v);
一切正常。
如果禁止这样做,那么将一个事件订阅到另一个事件有什么意义,为什么这样做时没有编译错误或警告?
答案 0 :(得分:5)
它失败的原因与此代码打印“2”相同:
int x = 2;
int y = x;
Action a = () => Console.WriteLine(y);
x = 3;
a();
此处,您的事件处理程序是[{1}} 在分配时的值 - 当您通过a.Evnt
时a
对Evnt
的影响a
进入B
的构造函数,这就是B
为事件处理程序获取的内容。
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"); };
}
你的问题的标题没有很好地表达;你没有分配一个事件,你正在分配一个事件处理程序。此外,“这不起作用”不是描述问题的有用方法。事情无穷无尽。我的第一个假设是你的代码甚至不会编译。下一次,请描述您希望看到的行为,以及您实际看到的内容。说它是否无法编译,或在运行时抛出异常,或者只是悄悄地做了一些你没想到的事情。如果出现错误消息或异常消息,请提供消息文本。
答案 1 :(得分:0)
因为lambda会在通话时评估并捕获,否则+ =附加一次然后调用ref(不评估)