C# 我不知道';我不理解事件委托的双重语法

C# 我不知道';我不理解事件委托的双重语法,c#,C#,在回答我的另一个问题时,我读到: if (ValueChanged != null) { ValueChanged(sender, e); } 在第一种情况下,价值发生了什么变化?不是第二条指令中的函数?如何将相同的符号用于两个。。。和功能 在james的回答后更新:如果ValueChanged是一个对象,我怎么能像调用方法一样调用它?它是一种语法糖,还是一种背后有某种神秘机制的外来语法,比如调用ValueChanged.Invoke(sender,e) ValueChanged在这两种

在回答我的另一个问题时,我读到:

if (ValueChanged != null)
{
   ValueChanged(sender, e);
}
在第一种情况下,价值发生了什么变化?不是第二条指令中的函数?如何将相同的符号用于两个。。。和功能


在james的回答后更新:如果ValueChanged是一个对象,我怎么能像调用方法一样调用它?它是一种语法糖,还是一种背后有某种神秘机制的外来语法,比如调用ValueChanged.Invoke(sender,e)

ValueChanged在这两种情况下都是相同的

首先,检查它是否为null,如果没有订阅者,就会出现这种情况


其次,使用类似方法的语法执行委托。

事件只是委托-对其他地方函数的引用。当调用上述事件时,我们调用的是委托。由于委托只是对函数的引用,因此我们需要处理以前可能没有设置它的情况(即null)

ValueChanged是对一个或多个函数的引用。如果没有引用,则该值将为null。如果该值不为null,则
ValueChanged(sender,e)将调用所有引用的函数语法。

ValueChanged是一个多播委托,它是一个对象。如果没有人订阅该事件,则该事件可以为null,因此需要进行检查。如果要避免检查,可以定义一个空委托并将其分配给事件

public event EventHandler ValueChanged = delegate {};
您现在可以调用ValueChanged(sender,e),因为ValueChanged永远不能为null。

与C语言中的许多功能一样,有一些语言功能可以让事情变得更简单。将
ValueChanged
视为一个字段,并检查它是否为null(委托人将在内部检查订阅者),第二个字段为

ValueChanged.Invoke(sender, e);

当然,事件的实际特征不仅仅是一个领域。它公开了订阅者的公共添加/删除属性以及用于调用的私有字段

但我仍然不明白,如果ValueChanged是一个对象,我怎么能像调用函数一样调用它呢?它是一种句法上的糖,背后有某种神秘的机制吗?+1从来没有想过这样初始化它。这将使代码更加干净,无需强制的空检查。是的,ValueChanged是一个对象。它是从MultiCastDelegate派生的EventHandler实例。调用ValueChanged(发送方,args)时,编译器将其转换为ValueChanged.Invoke(发送方,args)。所以,是的,只是语法上的糖。在.NET Reflector中创建简单的程序并查看编译后的输出(作为反编译C#和MSIL)是值得的。您将了解到C#编译器为您所做的大量工作……它仍然可以为null,以注销事件处理程序。Pseudo:对于处理程序事件-=处理程序中的每个处理程序。这个解决方案同样健壮,但不够健壮,所以我随时都会进行null检查是的,您可以编写代码来删除所有事件处理程序,从而删除空委托{}。通常,您不应该删除未订阅的事件处理程序。所以这真的是一个bug。同样容易的是,您可以编写代码,在另一个线程尝试执行事件处理程序时将其置空。因此,在空检查中有一个竞争条件。代码是防御性的,而不是荒谬的。