C# PropertyChangedEventHandler是如何工作的?

C# PropertyChangedEventHandler是如何工作的?,c#,wpf,events,propertychanged,C#,Wpf,Events,Propertychanged,这是一个非常简单的问题,但我想知道是否有人可以解释第四行实际上在做什么?因此,第一行向处理程序提供一个事件。我真的不知道在什么情况下处理程序会返回null,或者最后一行会做什么 当您将对象和更改的属性传递给处理程序时,它会对它们做什么 PropertyChangedEventHandler handler = PropertyChanged; //property changed is the event if (handler != null) { handler(this, new

这是一个非常简单的问题,但我想知道是否有人可以解释第四行实际上在做什么?因此,第一行向处理程序提供一个事件。我真的不知道在什么情况下处理程序会返回null,或者最后一行会做什么

当您将对象和更改的属性传递给处理程序时,它会对它们做什么

PropertyChangedEventHandler handler = PropertyChanged; //property changed is the event

if (handler != null)
{
    handler(this, new PropertyChangedEventArgs(name));
}

我想我是用这个来得到这个结果的,但我想完全理解它在做什么。

处理程序
可以为null,如果没有处理程序要处理,则第四行为给定的属性名引发事件(它执行所有订阅的处理程序)


通常,当您使用绑定时,WPF框架将订阅
PropertyChanged
,因此一旦绑定的属性更改,它就可以更新绑定。

PropertyChanged
是这样声明的事件,根据其在接口中的定义:

public event PropertyChangedEventHandler PropertyChanged;
这样定义的实际上是事件处理程序列表的语法糖,您可以通过订阅向其中添加委托(即对函数的引用),或通过取消订阅删除委托

现在,当您调用一个事件时,即,
PropertyChanged(…)
,那么内部发生的是,内部列表中的每个委托都会使用参数单独调用。这将告诉事件的所有订阅者事件已经发生

现在,使用
handler
变量的原因是
PropertyChanged
可以为空。如果没有订阅,则调用事件(或者更确切地说,调用事件处理程序列表)将不起作用,因此这只是确保您可以实际执行处理程序的一种方法。

如果您刚刚执行了:

PropertyChanged(this, new PropertyChangedEventArgs(name))
如果没有人订阅事件
PropertyChanged
,您将获得
NullReferenceException
。要抵消此影响,请添加空检查:

if(PropertyChanged != null)
{
    PropertyChanged(this, new PropertyChangedEventArgs(name))
}
现在,如果您正在使用多线程,则有人可以在null检查和事件调用之间取消订阅,因此您仍然可以得到
NullReferenceException
。为了处理这个问题,我们将事件处理程序复制到一个临时变量

  PropertyChangedEventHandler handler = PropertyChanged;
  if (handler != null)
  {
    handler(this, new PropertyChangedEventArgs(name));
  }
现在,如果有人取消订阅该事件,我们的临时变量
handler
仍将指向旧函数,而此代码现在无法抛出
NullReferenceException

大多数情况下,您会看到人们使用关键字
var
,这使得您不需要键入临时变量的完整类型,这是您在代码中最常见的形式

  var handler = PropertyChanged;
  if (handler != null)
  {
    handler(this, new PropertyChangedEventArgs(name));
  }

没有上下文就很难说。您使用的是什么框架?这不是BCL的一部分,它可能是您正在检查/使用的某个MVVM框架。对于
PropertyChangedEventHandler
,它看起来没有什么特殊之处。这就是处理程序的工作原理。威尔的评论是荒谬的。这是标记为WPF的。PropertyChangedEventHandler位于System.ComponentModel中。没有MVVM框架——MVVM是一种体系结构模式,对WPF有用,但不是必需的。无论如何,这个问题是关于事件处理程序如何在C#中工作的,答案并不特定于任何特定的事件或框架。“第一行给处理程序一个事件”--不,它声明了一个变量,
handler
,并用
PropertyChanged
的值初始化它。。。在竞争条件下,复制处理程序不会调用刚刚指定的函数吗?这仅仅是公认的做生意的方式,还是我遗漏了什么?@ZachMierzejewski是的,这是预期的行为。订阅者有责任知道,即使在多线程情况下取消订阅,您仍然可以获得对该方法的最后调用。NET中内置的类的所有事件都使用此模式。