如何初始化事件

本文关键字:事件 初始化 | 更新日期: 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,而不是命名方法。