在c#中,如何在将方法附加到事件时传递参数

本文关键字:事件 参数 方法 | 更新日期: 2023-09-27 18:10:44

我试图将参数发送到一个方法,该方法在附加事件侦听器时由事件调用,我可以在一个匿名方法中创建参数,该方法工作良好,但我理想地希望使其更简洁,如下面的例子所示,这是抛出以下编译器错误:

操作符'+='不能应用于'System '类型的操作数。EventHandler'和'void'

ConfigFileWritten += (sender, args) =>
{
    string prefix = "IFMDE";
    bool enabled = true;
    SetConfigInterfaceEnabled(prefix, enabled);
};
//this line is throwing a compiler error 
ConfigFileWritten += SetConfigInterfaceEnabled("",true);

是否有可能像我提议的那样重构代码?

在c#中,如何在将方法附加到事件时传递参数

不是那样的。您正在做的是试图将调用 SetConfigInterfaceEnabled的结果附加为事件处理程序,这当然是不可能的(结果必须是EventHandler委托,但它只是void)。

你能做的是

ConfigFileWritten += (s, e) => SetConfigInterfaceEnabled("",true);

这里的事件处理程序是一个lambda函数,具有适当的签名(带有两个隐式类型的参数),它依次调用SetConfigInterfaceEnabled。它的唯一目的是使SetConfigInterfaceEnabled的签名适应预期的EventHandler

为了完整起见,我应该提到,尽管需要这样做是非常不寻常的,但如果SetConfigInterfaceEnabled是一个创建委托的工厂方法,您可以使用您建议的语法:

EventHandler SetConfigInterfaceEnabledDelegate(string s, bool b)
{
    return (o, e) => SetConfigInterfaceEnabled(s, b);
}
ConfigFileWritten += SetConfigInterfaceEnabledDelegate("", true);

您可以通过不对按值传递的参数使用变量来使它更简洁,像这样:

ConfigFileWritten += (sender, args) => {
    SetConfigInterfaceEnabled("IFMDE", true);
};

当编译器看到上述内容时,它不会立即调用SetConfigInterfaceEnabled。相反,它创建一个可以在运行时调用的对象,这样当您调用它时,就会调用SetConfigInterfaceEnabled。换句话说,=>创建了一个委托,允许您延迟对SetConfigInterfaceEnabled的调用。

但是,当编译器看到

ConfigFileWritten += SetConfigInterfaceEnabled("IFMDE", true);

它将其解释为立即调用SetConfigInterfaceEnabled 的指令,并使用从它返回的委托作为事件处理程序。当然这是不可能的,因为SetConfigInterfaceEnabled不返回委托。

如果ConfigFileWritten事件处理程序是您自己的类型,您可以在上升事件时传递参数。从EventArgs中派生您自己的事件参数类型并传递参数。它可以给你更多的灵活性,你不必在事件处理程序中硬编码参数。