如何初始化事件
本文关键字:事件 初始化 | 更新日期: 2023-09-27 18:29:12
我有一个类,它包含这样的事件
public class A
{
public event Func<string, string> Message;
public void Calling()
{
Message("Hello world!");
}
}
如果我调用Calling()
方法,但还没有人订阅Message
事件,则它为null并引发异常。
如何初始化我的事件?
事件已初始化。至值null
。修复方法是先检查null。规范方法如下:
public void Calling()
{
Func<string, string> handler = Message;
if (handler != null)
{
handler("Hello world!");
}
}
请注意,在进行检查之前,会将事件值复制到本地。这样可以确保在检查null
和调用事件之间不会对事件进行并发更改。在许多程序中,这是不需要的(没有并发),您可以安全地直接检查事件本身。
如果您使用的是支持null条件运算符的C#版本(6.0或更高版本),那么上面的内容可以很好地简化为:
public void Calling()
{
Message?.Invoke("Hello world!");
}
编译器将为您生成引用的中间副本,检查其是否为null
,并且仅在Invoke()
方法为非null时调用它。
您不需要初始化事件,而是需要检查Calling方法中的null:
public void Calling()
{
if (Message != null)
Message("Hello World!");
}
在类中调用事件之前检查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
检查解决了问题时,它每次引发事件时都会调用一个无所事事的函数。当然不推荐,但这是"初始化"事件的唯一方法。
虽然这不是你的问题,但我会把它放在那里。您可以通过"null检查"事件来检查是否有人在监听该事件。这可以确保它不会执行该方法(并随后引发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
可以命名为任何名称。我只是为了清楚起见才用的。它也可以是匿名方法或lambdas,而不是命名方法。