为什么我不能从扩展方法调用PropertyChanged事件?

我试图编写一个类来避免像“RaisePropertyChanged”这样的方法。 我知道我可以从具有该实现的类inheritance,但在某些情况下我不能。 我尝试使用扩展方法,但Visual Studio抱怨。

public static class Extension { public static void RaisePropertyChanged(this INotifyPropertyChanged predicate, string propertyName) { if (predicate.PropertyChanged != null) { predicate.PropertyChanged(propertyName, new PropertyChangedEventArgs(propertyName)); } } } 

它说:

“事件’ System.ComponentModel.INotifyPropertyChanged.PropertyChanged’只能出现在+ =或 – =的左侧

里德是对的。 但是,我看到你要做的事情(让你的代码可以重复使用 – 对你有好处 ); 我只想指出,通常可以通过接受PropertyChangedEventHandler 委托本身并在INotifyPropertyChanged实现中传递它来轻松解决这个问题:

 public static void Raise(this PropertyChangedEventHandler handler, object sender, string propertyName) { if (handler != null) { handler(sender, new PropertyChangedEventArgs(propertyName)); } } 

然后从实现INotifyPropertyChanged的类中,您可以像这样调用此扩展方法:

 PropertyChanged.Raise(this, "MyProperty"); 

这是因为, 正如Marc所说 ,在声明事件的类中,您可以像字段一样访问它(这意味着您可以将它作为委托参数传递给方法,包括扩展方法)。

您只能从定义它的类中引发事件。

这一行:

 predicate.PropertyChanged(propertyName, new PropertyChangedEventArgs(propertyName)); 

将失败,因为predicate不是定义此扩展方法的类。

这部分原因通常是通过基类而不是使用Extension方法来处理。

事件实际上只是一个带有添加/删除的API(技术上,CLI中有一个可选的“调用”,但c#编译器不提供它)。

你在那里有一个类似场地的事件; 类似字段的事件充当声明类型之外的添加/删除API,并且仅声明类型的字段中起作用,并且仅在需要将其视为委托时 – 最常见的是:调用订阅者(这是一个c#4中的细微变化;在c#4之前,来自类型内部所有访问对该字段起作用,包括+ = / – =)。

根据定义,扩展方法不能在声明类型中 – 只有顶级(非嵌套)静态类可以提供扩展方法; 所以没有任何扩展方法可以直接调用类似字段的事件。

使用event关键字定义事件时,C#编译器实际上会在后台为您生成许多内容。

 event EventHandler MyEvent; 

翻译成类似的东西(虽然不完全是因为它实际上增加了一些锁定和其他检查)…

 private EventHandler _myEvent; public EventHandler MyEvent { add( EventHandler handler ) { _myEvent += handler; } remove( EventHandler handler ) { _myEvent -= handler; } } 

正如您所看到的,实际的EventHandler _myEvent是私有的,无法直接调用。