2

为什么我不能直接将自定义事件参数传递给订阅我的事件的方法,即使我的自定义事件 args 类直接继承自EventArgs

例如,考虑以下两个类。一个是我要使用的类,另一个继承自EventArgs,并包含一些与事件相关的附加信息:

using System;

namespace ConsoleApplication11
{
    class MyClass
    {
        public event EventHandler MyEvent;

        public void MyMethod(int myNumber)
        {
            Console.WriteLine(myNumber);

            if(myNumber == 7)
            {
                MyEvent.Invoke(null, new MyCustomEvent() { Foo = "Bar" });
            }
        }
    }

    class MyCustomEvent : EventArgs
    {
        public string Foo { get; set; }
    }
}

因此,如果将数字 7 传递给MyMethod,我想调用MyEventMyCustomEvent类的新实例传递给订阅我的事件的任何方法。

我从我的主程序中订阅了这个,如下所示:

using System;

namespace ConsoleApplication11
{
    class Program
    {
        static void Main(string[] args)
        {
            MyClass myClass = new MyClass();
            myClass.MyEvent += new EventHandler(myClass_MyEvent);

            for (int i = 0; i < 9; i++)
            {
                myClass.MyMethod(i);
            }
        }

        static void myClass_MyEvent(object sender, EventArgs e)
        {
            //Do Stuff
        }
    }
}

即使我在MyCustomEvent调用事件时传入了一个对象,如果我将订阅我的事件的方法中的第二个参数更改为一个MyCustomEvent对象,我会得到一个编译错误。我需要将EventArgs对象显式转换为 a MyCustomEvent,然后才能访问类中的任何其他字段/方法等。

当使用具有许多不同事件的对象时,每个事件都有一个唯一相关的自定义EventArgs类,跟踪每个订阅每个事件的方法中的 EventArgs 需要强制转换可能会有点混乱。

如果我可以将我的自定义 EventArgs 类直接传递到订阅我的事件的方法中,那会容易得多。

这是一种可能吗?

谢谢

4

5 回答 5

5

不要将您的事件声明为 type EventHandler,而是创建一个专门使用您的自定义事件 args 类的新委托:

public delegate void MyEventHandler(object sender, MyEventArgs args);
public event MyEventHandler MyEvent;

现在您可以直接传递参数而无需强制转换。

另一种选择是使用泛型EventHandler<T>

public event EventHandler<MyEventArgs> MyEvent;

我更喜欢前者,因为你可以给委托类型一个更具描述性的名称,尽管后者更快一些。

于 2012-07-16T17:05:03.153 回答
1

使用以下通用版本声明您的事件EventHandler

public event EventHandler<MyCustomEvent> MyEvent;
于 2012-07-16T17:03:51.470 回答
1

而不是使用默认事件处理程序,只需定义适合您要实现的签名的自己的事件处理程序......

public delegate void MyEventHandler(object sender, MyCustomEventArgs e)
public event MyEventHandler MyEvent;
于 2012-07-16T17:04:40.267 回答
1

如果我理解你的问题是错误的,请原谅我。EventArgs没有看到任何自定义类,我有点困惑。

你不能像这样制作方法签名

static void myClass_MyEvent(object sender, CustomEventArgs e)

对于期望一个事件

static void myClass_MyEvent(object sender, EventArgs e)

那是反向多态性,而多态性不能反向工作。

假设您的事件访问 a e.OnlyInCustomEventArgs,但传递给基础对象EventArgs. 然后合同就被打破了。

现在你能做的是

static void myClass_MyEvent(object sender, EventArgs e)
{
    CustomEventArgs cea = (CustomEventArgs)e;
}
于 2012-07-16T17:06:25.697 回答
0

这是正确实现的自定义 arg 事件处理程序的完整代码。

class MyClass
{
    public event EventHandler<MyCustomEventArgs> MyEvent;

    public void MyMethod(int myNumber)
    {
        Console.WriteLine(myNumber);

        if (myNumber == 7)
        {
            MyEvent.Invoke(null, new MyCustomEventArgs() { Foo = "Bar" });
        }
    }
}

class MyCustomEventArgs : EventArgs
{
    public string Foo { get; set; }
}


class Program
{
    static void Main(string[] args)
    {
        MyClass myClass = new MyClass();
        myClass.MyEvent += new EventHandler<MyCustomEventArgs>(myClass_MyEvent);

        for (int i = 0; i < 9; i++)
        {
            myClass.MyMethod(i);
        }
    }

    //This is the method signature that you need to use to handle the event
    static void myClass_MyEvent(object sender, MyCustomEventArgs e)
    {
        Console.WriteLine(e.Foo); // prints "Bar"
        //Do Stuff
    }

    //If you need to handle more than one type of custom event args
    static void myClass_MyEvent<T>(object sender, T e) where T : EventArgs
    {
        //Do Stuff
    }
}
于 2014-08-28T14:18:59.297 回答