为什么我不能直接将自定义事件参数传递给订阅我的事件的方法,即使我的自定义事件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
,我想调用MyEvent
将MyCustomEvent
类的新实例传递给订阅我的事件的任何方法。
我从我的主程序订阅了这个:
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
对象强制转换为MyCustomEvent
。
当处理具有许多不同事件的对象时,每个事件都有一个唯一的相关自定义EventArgs
类,跟踪订阅每个事件的每个方法中的EventArgs需要被转换为什么有点乱。
如果我可以将自定义EventArgs类直接传递给订阅我的事件的方法,那将会容易得多。
这可能吗?
由于
答案 0 :(得分:5)
创建一个专门使用自定义事件args类的新委托,而不是将事件声明为EventHandler
类型:
public delegate void MyEventHandler(object sender, MyEventArgs args);
public event MyEventHandler MyEvent;
现在你可以直接传递参数而不需要强制转换。
另一种选择是使用通用EventHandler<T>
:
public event EventHandler<MyEventArgs> MyEvent;
我更喜欢前者,因为您可以为委托类型提供更具描述性的名称,尽管后者更快一些。
答案 1 :(得分:1)
使用EventHandler
的通用版本声明您的活动:
public event EventHandler<MyCustomEvent> MyEvent;
答案 2 :(得分:1)
而不是使用默认事件处理程序,只需定义适合您尝试实现的签名的自己...
public delegate void MyEventHandler(object sender, MyCustomEventArgs e)
public event MyEventHandler MyEvent;
答案 3 :(得分:1)
EventArgs
类,我有点困惑。
您不能制作像
这样的方法签名static void myClass_MyEvent(object sender, CustomEventArgs e)
表示需要
的事件static void myClass_MyEvent(object sender, EventArgs e)
这是向后的多态性,并且多态性不会向后工作。
假设您的事件访问e.OnlyInCustomEventArgs
,而是传递基础对象EventArgs
。然后合同被打破了。
现在你可以做的是
static void myClass_MyEvent(object sender, EventArgs e)
{
CustomEventArgs cea = (CustomEventArgs)e;
}
答案 4 :(得分: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
}
}