如何初始化事件

问题描述 投票:3回答:5

我有一堂课,有这样的事件

public class A
{
    public event Func<string, string> Message;

    public void Calling()
    {
        Message("Hello world!");
    }
}

如果我调用Calling()方法,但还没有人订阅Message事件,它为null,并引发异常。

我如何初始化我的活动?

c# .net events
5个回答
5
投票

您不初始化事件,而是需要在Calling方法中检查null:

public void Calling()
{
    if (Message != null)
        Message("Hello World!");
}

5
投票

事件已初始化。取值为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()方法。


3
投票

在课堂上调用您的活动之前,请先检查null,以查看是否有人订阅了该活动。

public void Calling()
{
    if (Message != null)
        Message("Hello world!");
}

参见:Events Tutorial

[调用事件:类声明了事件后,就可以该事件就像指示的委托类型的字段一样。场如果没有客户端将委托连接到事件,否则它是指当事件被调用。 因此,通常首先要调用一个事件检查null,然后调用事件


1
投票

您不能。

事件是默认情况下的null,这就是为什么良好实践要求您在使用事件之前对其进行检查:

public void Calling()
{
    if (Message != null)
       Message("Hello World");
}

您未在此处使用返回值;有点奇怪,但也许只是因为这是一个例证。

您还可以在构造函数中将其初始化为空白函数,但这只是浪费资源:

public A()
{
    Message += (s) => { return String.Empty; };
}

现在,当简单的null检查解决了该问题时,每次引发事件时,它都会调用no-nothing函数。绝对not推荐,但这是“初始化”事件的唯一方法。


1
投票

尽管,这不是你的问题,我将把它扔在那里。您可以通过“空检查”来检查是否有人在听事件。这样可以确保它不会执行该方法(并随后引发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,而不是命名方法。

© www.soinside.com 2019 - 2024. All rights reserved.