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

C# 是否将额外参数传递给事件处理程序?,c#,events,callback,C#,Events,Callback,假设我想在分配事件处理程序时传递一些额外的数据。考虑下面的代码: private void设置(字符串someData) { assignHandler(evHandler); } 公共无效evHandler(对象发送方) { //这里需要一些数据!!! } 如何将someData放入我的evHandler方法中?好吧,最简单的方法id是将someData作为成员变量,如下所示: public class MyClass { private string _eventData;

假设我想在分配事件处理程序时传递一些额外的数据。考虑下面的代码:

private void设置(字符串someData)
{
assignHandler(evHandler);
}
公共无效evHandler(对象发送方)
{
//这里需要一些数据!!!
}

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

好吧,最简单的方法id是将
someData
作为成员变量,如下所示:

public class MyClass
{
    private string _eventData;

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

    public void evHandler()
    {
        // do something with _eventData here
    }
}
我不确定这是最好的方法,但这实际上取决于事件类型、对象等。

捕获的变量:

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

public void evHandler(Object sender, string someData)
{
    // use someData here
}
或(C#2.0备选方案):


您可以尝试这样做:

string yourObject;

theClassWithTheEvent.myEvent += (sender, model) =>
{
 yourObject = "somthing";
}

您可以基于对象创建具有其他属性的自定义对象:

class CustomObject : Object
{
    public string SomeData;
}

private void setup(string someData)
{
    CustomObject customObject = new CustomObject { SomeData = someData };
    CustomObject.assignHandler(evHandler);
}

public void evHandler(Object sender)
{
    string someData = ((CustomObject)sender).SomeData;
}

如果数据在初始化后不应再更改,您也可以添加自定义构造函数,例如。

我很难理解@spender上面的示例,尤其是关于:
Object.assignHandler((sender)=>evHandler(sender,someData))Object.assignHandler
。所以我在谷歌上搜索了一下,找到了。Peter Duniho的答案在我脑海中闪现(这不是我的作品):

剪断

通常的方法是使用带有事件处理程序的匿名方法 那有你修改过的签名。例如:

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

button.Click += delegate(object sender, EventArgs e) 
{ Onbutton_click(sender, e, 172); };
当然,您不必传入172,甚至不必生成第三个参数 一个int.:)

/剪断

使用该示例,我能够将两个自定义的
ComboBoxItem
对象传递给
计时器。使用lambda表示法的已用事件:

simulatorTimer.Elapsed +=
(sender, e) => onTimedEvent(sender, e,
(ComboBoxItem) cbPressureSetting.SelectedItem,
(ComboBoxItem) cbTemperatureSetting.SelectedItem);
然后进入它的处理程序:

static void onTimedEvent(object sender, EventArgs e, ComboBoxItem pressure, ComboBoxItem temperature)
    {
        Console.WriteLine("Requested pressure: {0} PSIA\nRequested temperature: {1}° C", pressure, temperature);
    }
这不是上面示例中的任何新代码,但它确实演示了如何解释它们。希望像我这样的人会觉得它很有教育意义和有用,这样他们就不会像我一样花几个小时试图理解这个概念


这段代码在我的项目中起作用(除了
ComboBoxItem
对象的非线程安全异常,我不相信它会改变示例的工作方式)。我现在就明白了。

这是我的单行解决方案,它将额外的参数传递给计时器处理程序

private void OnFailed(uint errorCode, string message)
{
    ThreadPoolTimer.CreateTimer((timer) => {
    UI.ErrorMessage = string.Format("Error: 0x{0:X} {1}", errorCode, message);
    }, System.TimeSpan.FromMilliseconds(100));
}

我类似的问题被标记为重复,所以我想我应该在这里添加一个答案,因为它不会让我回答我的问题

class Program
    {
        delegate void ComponentEventHandler(params dynamic[] args);

        event ComponentEventHandler onTest;

        static void Main(string[] args)
        {  
            Program prg = new Program();

            // can be bound to event and called that way
            prg.onTest += prg.Test;
            prg.onTest.Invoke("What", 5, 12.0);

            Console.ReadKey();
        }

        public void Test(params dynamic[] values)
        {
            // assign our params to variables
            string name = values[0];
            int age = values[1];
            double value = values[2];

            Console.WriteLine(name);
            Console.WriteLine(age);
            Console.WriteLine(value);
        }
    }

是否捕获变量==闭包?@Matt-是的,捕获变量是词汇闭包。为了澄清,第一个解决方案是否对C#.NET 2.0无效?@whydna第一个解决方案需要C#3.0或更高版本;有一个微妙的语法补充,我们正在考虑这个方法,但是安装程序可能会被调用多次不同的someData。每个处理程序的数据应该是唯一的。在这种情况下,spender或Marc的解决方案要好得多。这是一个很好的解决方案,但是如果EventHandler已经有了TARG呢。比如+=neweventhandler(evHandler)?嗨@Lily,你问什么还不完全清楚。发布一个更详细的问题(而不是评论)和一些代码来演示您正在尝试做的事情可能更好。谢谢,这解决了我遇到的一个问题,但我是C#新手,所以您介意解释一下这种语言结构是什么,还是给我一个关键字让谷歌解释一下?@TomSmilack,看看lambda表达式和用闭包捕获变量。基本上,lambda表达式是一种声明方法的简写方式(…等等,但这是另一回事)我在这个问题上有一个更标准的解决方案,第一个答案:我在这个问题上有一个更标准的解决方案,第一个答案唯一的问题是如果你想取消订阅活动(很可能你应该),您将通过匿名代理取消订阅,您不应该这样做-请参阅。
private void OnFailed(uint errorCode, string message)
{
    ThreadPoolTimer.CreateTimer((timer) => {
    UI.ErrorMessage = string.Format("Error: 0x{0:X} {1}", errorCode, message);
    }, System.TimeSpan.FromMilliseconds(100));
}
class Program
    {
        delegate void ComponentEventHandler(params dynamic[] args);

        event ComponentEventHandler onTest;

        static void Main(string[] args)
        {  
            Program prg = new Program();

            // can be bound to event and called that way
            prg.onTest += prg.Test;
            prg.onTest.Invoke("What", 5, 12.0);

            Console.ReadKey();
        }

        public void Test(params dynamic[] values)
        {
            // assign our params to variables
            string name = values[0];
            int age = values[1];
            double value = values[2];

            Console.WriteLine(name);
            Console.WriteLine(age);
            Console.WriteLine(value);
        }
    }