这个C#语法结构是做什么用的?

3

我在另一个帖子上看到了这个问题,但是让我感到困惑...

public class MyClass : INotifyPropertyChanged
{
   public event PropertyChangedEventHandler PropertyChanged;  

   protected void NotifyPropertyChanged(String info)
   {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(info));
        }
   }  

   public string MyProperty
   {
       set
       {
           if (_myProperty != value)
           {
               _myProperty = value;
               NotifyPropertyChanged("MyProperty");
           }
       }
   }
}

MyClass myClass = new MyClass();

myClass.PropertyChanged += delegate(object sender, PropertyChangedEventArgs e)
{
     actual = e.PropertyName;
};

说实话,我对最后几行的作用感到困惑,为什么用户要将委托分配给事件?他们不会将方法分配给它(作为事件处理程序),甚至可以将匿名方法作为事件处理程序吗?

我认为事件旨在封装委托.....?


请勿重复:https://dev59.com/hXRB5IYBdhLWcg3wr48V - mbeckish
1
事件处理程序 委托。 - Alex
我已经尽力回答这个问题了,但是它有点混乱...你能否尝试澄清一下? - Jon Skeet
那么,对于这么简单的处理程序,使用lambda符号是否同样有效呢?myClass.PropertyChanged += (sender, e)=> actual = e.PropertyName; - Tetsujin no Oni
6个回答

4

无论何时,您都需要使用委托来订阅事件(或取消订阅)。即使您这样做:

button.Click += HandleButtonClick;

这相当于

button.Click += new EventHandler(HandleButtonClick);

当你说:
“不会给它分配一个方法(作为事件处理程序)或甚至是匿名方法作为事件处理程序吗?”
这正是代码的最后几行所做的。 这就是“delegate (...) { ... }”所表示的。
“我以为事件是用来封装委托的......?”
事件使用委托作为观察者,提供了观察者模式的实现。

“你总是使用委托来订阅事件(或取消订阅事件),而不是使用事件本身”,这句话应该改为“使用委托”吗? - Ani
Jon,你说的观察者设计模式很有趣,你是在说事件是为了解决这个设计模式而创建的吗? - Exitos

1

这个语法是在C# 2.0中引入的。 他们在这里使用了匿名方法,而不是必须创建类的实际实例方法。一般认为这样更清晰。

在C# 3及以上版本中,也可以使用Lambda表达式。


添加委托的lambda符号将会很有用,我认为... - Tetsujin no Oni
myClass.PropertyChanged += (x,y) => actual = y.PropertyName; 我的类.属性更改 += (x,y) => 实际 = y.PropertyName; - Jimmy W
好的,这很有道理。我认为可能是匿名方法的语法使它变得混淆,因为它包含了“delegate”这个词。有人告诉我你可以有一个匿名方法。我想他们的意思是使用匿名方法的委托。 - Exitos
@Exitos:我不明白为什么这会让它变得混乱 - 它正在创建委托类型的实例。 - Jon Skeet

1
从技术上讲,你是正确的;事件封装委托。然而,事件处理程序本身就是委托。

1

描述

该类实现了INotifyPropertyChanged接口。

MSDN 通知客户端属性值已更改。

INotifyPropertyChanged接口用于通知客户端(通常是绑定客户端)属性值已更改。

例如,这在像Datagrid这样的控件上使用。它向控件发出信号,表明属性已更改,控件应重新呈现。

关于事件

您始终订阅事件。

MyClass myClass = new MyClass();
myClass.PropertyChanged += delegate(object sender, PropertyChangedEventArgs e)
{
     actual = e.PropertyName;
};

正在执行相同的操作

MyClass myClass = new MyClass();
myClass.PropertyChanged += new PropertyChangedEventHandler(myClass_PropertyChanged);

void myClass_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
     actual = e.PropertyName;     
}

或者

MyClass myClass = new MyClass();
myClass.PropertyChanged += myClass_PropertyChanged;

void myClass_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
     actual = e.PropertyName;    
}

更多信息


1

+=匿名委托 添加到事件中。不需要创建一个带有签名 object sender, PropertyChangedEventArgs e 的命名方法,您可以使用 C#2.0 语法在另一个函数的主体中匿名创建这样的委托。另一种方法是使用 C#3.5+ 中更简洁的 lambda 语法:

myClass.PropertyChanged += (sender, e) { actual = e.PropertyName; };

1

他们并没有为事件分配一个委托,而是使用匿名方法向该事件添加了一个订阅者。

此外,顺带一提,NotifyPropertyChanged方法应更改为:

protected void NotifyPropertyChanged(String info)
{
    PropertyChangedEventHandler handler = PropertyChanged;
    if (handler != null)
    {
        handler(this, new PropertyChangedEventArgs(info));
    }
}

由于在空值检查和委托调用之间存在潜在的竞态条件。


保护委托将使你免受奇怪的错误报告之苦。 - Tetsujin no Oni

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接