我有一堂课,有这样的事件
public class A
{
public event Func<string, string> Message;
public void Calling()
{
Message("Hello world!");
}
}
如果我调用Calling()
方法,但还没有人订阅Message
事件,它为null,并引发异常。
我如何初始化我的活动?
您不初始化事件,而是需要在Calling方法中检查null:
public void Calling()
{
if (Message != null)
Message("Hello World!");
}
事件是已初始化。取值为null
。解决方法是先检查是否为空。规范方法如下:
public void Calling()
{
Func<string, string> handler = Message;
if (handler != null)
{
handler("Hello world!");
}
}
注意,在检查之前,事件值已复制到本地。这样可确保在检查null
的时间与调用它的时间之间不会发生事件的并发更改。在许多程序中,不需要(无需并发),您可以放心地直接检查事件本身。
如果您使用的是支持空条件运算符的C#版本(6.0或更高版本,则上面的代码可以很好地简化为:]
public void Calling()
{
Message?.Invoke("Hello world!");
}
编译器将为您生成引用的中间副本,将其检查为null
,并且仅在非null时才调用Invoke()
方法。
在课堂上调用您的活动之前,请先检查null
,以查看是否有人订阅了该活动。
public void Calling()
{
if (Message != null)
Message("Hello world!");
}
[调用事件:类声明了事件后,就可以该事件就像指示的委托类型的字段一样。场如果没有客户端将委托连接到事件,否则它是指当事件被调用。 因此,通常首先要调用一个事件检查null,然后调用事件。
您不能。
事件是默认情况下的null,这就是为什么良好实践要求您在使用事件之前对其进行检查:
public void Calling()
{
if (Message != null)
Message("Hello World");
}
您未在此处使用返回值;有点奇怪,但也许只是因为这是一个例证。
您还可以在构造函数中将其初始化为空白函数,但这只是浪费资源:
public A()
{
Message += (s) => { return String.Empty; };
}
现在,当简单的null
检查解决了该问题时,每次引发事件时,它都会调用no-nothing函数。绝对not推荐,但这是“初始化”事件的唯一方法。
尽管,这不是你的问题,我将把它扔在那里。您可以通过“空检查”来检查是否有人在听事件。这样可以确保它不会执行该方法(并随后引发NullReferenceException)。
public void Calling()
{
if (Message != null)
Message("Hello World"); // Why are you ignoring the return value?
}
关于您的实际问题,某些东西必须引用类型为A
的对象(在您的示例中定义。)>
public class B { A MyA; public B() { MyA = new A(); } }
然后它必须订阅Message的事件。
public class B() { A MyA; public B() { MyA = new A(); MyA.Message += MessageHandler; } public string MessageHandler(string s) { // Do other code here and ensure you're returning a string as defined in your Message event. return s; } }
请注意,
MessageHandler
可以命名为任何名称。我只是为了清楚起见使用了它。它也可以是匿名方法或lambda,而不是命名方法。