C#将额外的参数传递给事件处理程序?

And*_*Hin 57 c# events callback

比方说,我想在分配事件处理程序时传递一些额外的数据.请考虑以下代码:

private void setup(string someData)
{
     Object.assignHandler(evHandler);
}

public void evHandler(Object sender)
{
    // need someData here!!!
}
Run Code Online (Sandbox Code Playgroud)

我如何将someData放入我的evHandler方法?

spe*_*der 54

private void setup(string someData)
{
     Object.assignHandler((sender) => evHandler(sender,someData));
}
public void evHandler(Object sender, string someData)
{
    // need someData here!!!
}
Run Code Online (Sandbox Code Playgroud)

  • 这是一个很好的解决方案,但是如果 EventHandler 已经有 TArgs 了怎么办?比如+= new EventHandler<AsyncCompletedEventArgs>(evHandler)? (2认同)

del*_*ttg 24

我很难搞清楚@ spender上面的例子,尤其是:Object.assignHandler((sender) => evHandler(sender,someData));因为Object.assignHandler字面意义上没有这样的东西.所以我做了一点谷歌搜索并找到了这个例子.Peter Duniho的回答是点击了我的脑袋(这不是我的工作):

SNIP

通常的方法是使用具有已修改签名的事件处理程序的匿名方法.例如:

void Onbutton_click(object sender, EventArgs e, int i) { ... }

button.Click += delegate(object sender, EventArgs e) 
{ Onbutton_click(sender, e, 172); };
Run Code Online (Sandbox Code Playgroud)

当然,您不必传入172,甚至不能将第三个参数设为int.:)

/剪断

使用该示例,我能够使用lambda表示法将两个自定义ComboBoxItem对象传递给Timer.Elapsed事件:

simulatorTimer.Elapsed +=
(sender, e) => onTimedEvent(sender, e,
(ComboBoxItem) cbPressureSetting.SelectedItem,
(ComboBoxItem) cbTemperatureSetting.SelectedItem);
Run Code Online (Sandbox Code Playgroud)

然后进入它的处理程序:

static void onTimedEvent(object sender, EventArgs e, ComboBoxItem pressure, ComboBoxItem temperature)
    {
        Console.WriteLine("Requested pressure: {0} PSIA\nRequested temperature: {1}° C", pressure, temperature);
    }
Run Code Online (Sandbox Code Playgroud)

这不是上面示例中的任何新代码,但它确实演示了如何解释它们.希望像我这样的人发现它具有指导性和实用性,所以他们不会像我一样花费数小时来理解这个概念.

这段代码适用于我的项目(除了非线程安全的异常ComboBoxItem,我不相信的对象会改变示例的工作原理).我现在正在搞清楚.

  • 唯一的问题是,如果您想取消订阅该活动(很可能应该这样做),您将通过匿名委托取消订阅,而您不应该这样做 - 请参阅[相关问题的答案](https ://stackoverflow.com/a/41199095/422845)。 (2认同)

Mar*_*ell 18

捕获的变量:

private void setup(string someData)
{
    Object.assignHandler((sender,args) => {
        evHandler(sender, someData);
    });
}

public void evHandler(Object sender, string someData)
{
    // use someData here
}
Run Code Online (Sandbox Code Playgroud)

或者(C#2.0替代方案):

    Object.assignHandler((EventHandler)delegate(object sender,EventArgs args) {
        evHandler(sender, someData);
    });
Run Code Online (Sandbox Code Playgroud)

  • 捕获变量===封闭? (2认同)
  • @Matt - 是的,捕获的变量是词法闭包. (2认同)