C#:理解事件语法

C#:理解事件语法,c#,C#,我需要一些帮助来了解如何创建新的自定义事件。我从 首先,我没有真正理解代表部分。在正常变量申报中 protected string str1; 但这里我有额外的(ChangingHandler)。我如何理解这一点?我知道这有点像是用一个变形金刚来处理这件事,但这让我有点不舒服 public event ChangingHandler Change 然后 我真的不明白新汽车的语法 C#中的事件有点像方法指针的集合。它说:“大家好,如果你们关心我,给我一个指向我可以调用的方法的指针,我会抓住它,

我需要一些帮助来了解如何创建新的自定义事件。我从

首先,我没有真正理解代表部分。在正常变量申报中

protected string str1;
但这里我有额外的(
ChangingHandler
)。我如何理解这一点?我知道这有点像是用一个变形金刚来处理这件事,但这让我有点不舒服

public event ChangingHandler Change
然后

我真的不明白新汽车的语法

C#中的事件有点像方法指针的集合。它说:“大家好,如果你们关心我,给我一个指向我可以调用的方法的指针,我会抓住它,当我想向全世界宣布发生了什么时,我会调用你们给我的所有方法。”

这样,有人可以给事件一个指向其方法的指针,称为“事件处理程序”。只要事件的所有者认为合适,事件就会调用此方法

从这个意义上讲,委托只不过是说明事件将接受哪种方法。你不能让一个人给事件一个不带参数的方法和一个带5参数的方法,它不知道如何调用它们。因此,委托是事件和事件处理程序之间的契约,告诉它们对方法签名的期望

在您的情况下,最好只使用
EventHandler
,它是一个内置的委托,形式为
void EventHandler(object sender,T eventArgs)
,用于您的事件委托,如下所示:

public event EventHandler<CarArgs> Change;
if (Change != null) // You wouldn't access an array without making sure it wasn't null, would you?
{
    Change(this, new CarArgs()); // This executes every method body in it's array using the signature definition the delegate defined.
    // The delegate simply exists so this code knows the method signature
    // so it can know how to call those method body's for you.
}

您正在给事件一个新的委托(函数指针),该委托指向您的car\u Change事件处理程序,告诉事件在准备就绪时调用您的car\u Change方法。代理(
newchangehandler(…)
只是将指针包装到car\u Change方法。

同样,事实证明您不需要
car.Change+=new car.ChangingHandler(car\u Change);
sytax,因为它不像您指出的那样直观


您可以简单地编写
car.Change+=car\u Change;
假设
car\u Change
具有正确的方法签名。

事件具有特定的签名。此签名定义侦听器在参数和返回类型方面的外观。此契约通过定义委托来表示。从代码示例:

public delegate void ChangingHandler (object sender, CarArgs ca);
这里,我们定义了一个委托,用于将
对象
CarArgs
作为参数,并使用
void
返回类型的方法

接下来,我们宣布该事件如下:

public event ChangingHandler Change;
因此,我们有一个名为
Change
的事件,该事件的侦听器必须与
ChangingHandler
委托具有相同的签名

然后我们需要一个侦听器方法:

private void car_Change(object sender, CarArgs ca) {
    MessageBox.Show(ca.Message());
} 
在这里,我们可以看到它如何与
ChangingHandler
委托具有相同的签名

最后,我们可以将listner附加到事件:

car.Change+=new Car.ChangingHandler(car_Change)
因此,我们创建一个新的
ChangingHandler
实例,该实例引用
car\u Change
方法,并将委托实例传递给事件

综上所述,我建议使用预定义的
EventHandler
委托,而不是创建自己的委托:

public event EventHandler<CarArgs> Change;
公共事件事件处理程序更改;

一种粗略的思考方式:委托类型定义了作为事件基础的“函数形状”。因此,
ChangingHandler
是函数必须看起来的样子

更进一步说,委托实例就像一个函数指针

public event ChangingHandler Change
定义了一个名为
Change
的函数指针,该指针将指向形状为
ChangingHandler
的函数

但是目前,这个函数指针没有指向任何东西。这就是
car.Change+=new car.ChangingHandler(car\u Change)
位的作用

分两步进行。委托不是普通的函数指针;它们实际上更像函数指针堆栈,可以将多个函数分配给委托。这就是为什么人们更常谈论“订阅”的原因将函数添加到事件将意味着在事件激发时将调用它。使用+=运算符将函数添加到委托“堆栈”中


你不能直接将函数添加到委托中,它是用委托本身来表示的。这是一种一次性的方式,在将函数添加到事件的同一行上创建一个新的对象;尽管从C#2.0开始,我相信你可以直接添加函数,而无需调用新的语法。

nts基于委托的概念,委托基本上是一个方法签名定义。仅此而已。就像在接口中如何定义方法签名,但没有实现它们一样,在继承该接口的所有类中都是这样做的

委托是方法签名的定义,您可以为其定义任意多个方法体,例如,给定此委托(方法签名定义):

您可以使用此委托(方法签名定义)定义实体,如下所示:

不过,这是一种旧的定义委托的方式,现在使用lambdas而不是delegate关键字来创建方法体更具可读性,就像我所做的那样,但这对问题并不重要

现在,可以将事件想象为一个委托(方法签名定义),具有一系列主体,这些主体被称为订阅事件,将方法主体订阅到事件的语法是
+=
,还有从事件订阅中删除方法主体的语法是
-=

因此,这里的代码为ChangingHandler委托定义了一个主体数组(方法签名定义):

您可以通过调用以下方法将主体(添加到数组)订阅到此分组:

public void SomeMethodWhichSubscribesADelegateBodyToAnEvent()
{
    ChangingHandler myChangingHandler = new ChangingHandler(
        delegate(object sender, EventArgs e) { /* the method body for myChangingHandler */ }
    );

    Change += myChangingHandler;
}
现在是除夕夜的全部原因
public event EventHandler<CarArgs> Change;
public delegate void ChangingHandler (object sender, CarArgs ca);
public void SomeMethodWhichCreatesADelegateBody()
{
    ChangingHandler myChangingHandler = new ChangingHandler(
        delegate(object sender, EventArgs e) { /* the method body for myChangingHandler */ }
    );
}
public event ChangingHandler Change;
public void SomeMethodWhichSubscribesADelegateBodyToAnEvent()
{
    ChangingHandler myChangingHandler = new ChangingHandler(
        delegate(object sender, EventArgs e) { /* the method body for myChangingHandler */ }
    );

    Change += myChangingHandler;
}
if (Change != null) // You wouldn't access an array without making sure it wasn't null, would you?
{
    Change(this, new CarArgs()); // This executes every method body in it's array using the signature definition the delegate defined.
    // The delegate simply exists so this code knows the method signature
    // so it can know how to call those method body's for you.
}