【问题标题】:C#: EventHandler delegateC#:事件处理程序委托
【发布时间】:2017-08-17 08:57:40
【问题描述】:
public delegate void EventHandler(object sender, EventArgs e);

在上面的代码中,EventHandler 是一个接受object sender, EventArgs e 的委托。但是,以下实现中的参数数量不匹配:

this.baptismApplication_add_button.Click += new System.EventHandler(this.baptismApplication_add_button_Click);

我可以看到senderthis.baptismApplication_add_button_Click,但是方法调用的哪一部分有EventArgs e?是隐含的吗?还是我做错了?

【问题讨论】:

    标签: c# events delegates event-handling


    【解决方案1】:

    delegate 是特殊类型。它们代表方法。这个:

    public delegate void EventHandler(object sender, EventArgs e);
    

    是否意味着要创建EventHandler,您需要传入两个参数sendere。这只是意味着

    EventHandler 表示签名为(object sender, EventArgs e) 的方法返回void

    要创建EventHandler,您需要传入一个具有所需签名的方法。比如这个方法:

    private void MyMethod(object sender, EventArgs e) {
    
    }
    

    您可以像这样创建EventHandler

    new EventHandler(MyMethod);
    

    注意我没有在方法名称后写()。这样做会调用该方法。我们不希望那样。这里我们只想参考它。

    让我们看另一个例子。

    public delegate void Action();
    

    要创建Action,您需要一个没有参数并返回void 的方法。像这样:

    private void MyMethod2() {}
    // ...
    new Action(MyMethod2);
    

    现在您已经了解了委托的工作原理,我们可以谈谈如何正确订阅Click 事件。

    正如我所说,EventHandler 的“构造函数”接受一个方法作为参数,所以你不应该在其中传递你的按钮。你需要一个方法。让我们写一个:

    private void ButtonPressed(object sender, EventArgs e) {
        Console.WriteLine("Hello World");
    }
    

    现在我们可以用这个方法创建委托了:

    yourButton.Click += new EventHandler(this.ButtonPressed);
    

    这实际上可以缩短为:

    yourButton.Click += ButtonPressed;
    

    现在每次按下按钮“Hello World”都会打印出来。

    【讨论】:

    • 发送者和 EventArgs 在哪一部分作为参数被传递?我似乎在我的代码中找不到它
    • @DonovanKeating 哈哈,好问题。 ButtonPress 的实际调用不是由您完成的。这是由按钮的代码完成的。您只需为按钮提供一种在按下时调用的方法。这就是为什么它被称为“代理”。你只需要给它一个正确签名的方法。
    • 所以我实际上看不到它,因为它是“隐藏的”?如果我制作自己的 EventHandler,我必须指定发送者和 EventArgs 对吗? :)
    • @DonovanKeating 在Button 的代码中的某处,它调用Click.Invoke(this, new EventArgs())。看到通过的两个参数了吗?如果你创建了一个引发事件的类,你只需要传递这两个参数。只需搜索 C# 事件示例代码。我相信你会发现很多内容。
    【解决方案2】:

    您混淆了委托签名和委托构造函数的签名。

    委托签名是void (object, EventArgs),但委托构造函数(您通过new System.EventHandler(...) 调用它)需要一个带有上述签名的方法,而不是一对参数。

    注意,可以省略显式的构造函数调用:

    this.baptismApplication_add_button.Click += this.baptismApplication_add_button_Click;
    

    编译器会将其转换为 EventHandler 构造函数调用。

    【讨论】:

    • 谢谢我现在明白了:)
    • @DonovanKeating 如果您认为某个答案可以回答您的问题,请考虑接受!
    • 我还有一个困惑。让我重新发表我的评论。
    • 但是 sender 和 EventArgs 在哪一部分作为参数被传递?我似乎在我的代码中找不到它。
    • @DonovanKeating: sendere 由委托调用者传递。特别是,当单击按钮时,它会查看是否有任何事件处理程序,并调用它们,将自身作为senderEventArgs.Empty 作为e 传递。这就是委托的发明目的 - 您将方法(委托)的引用传递给某些代码,然后该代码调用您的方法,提供所需的参数。
    【解决方案3】:
    += new System.EventHandler(this.baptismApplication_add_button_Click);
    

    应该是

    += new System.EventHandler(myhandler);
    

    其中myhandler 是一个处理程序方法,每个委托定义都有适当的匹配参数,例如

    private void myhandler(object sender, EventArgs e)
    {
    
    }
    

    【讨论】:

    • 谢谢我现在明白了:)。但是 sender 和 EventArgs 在哪一部分作为参数被传递?我似乎在我的代码中找不到它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-24
    • 1970-01-01
    相关资源
    最近更新 更多