代表性的异质性名单

时间:2010-01-23 17:27:48

标签: c# delegates

是否可以创建包含不同类型委托的列表? 例如,考虑这两位代表:

class MyEventArg1 : EventArgs {}
class MyEventArg2 : EventArgs {}

EventHandler<MyEventArgs1> handler1;
EventHandler<MyEventArgs2> handler2;

我想做那样的事情:

List<EventHandler<EventArgs>> handlers = new List<EventHandler<EventArgs>>();

handlers.Add((EventHandler<EventArgs>)handler1);
handlers.Add((EventHandler<EventArgs>)handler2);

但是从一个代表到另一个代表的演员似乎是不可能的。 我的目标是将代表存储在列表中而不是调用它们;但只是自动取消注册。

由于

3 个答案:

答案 0 :(得分:1)

感谢generics variance,您将能够在C#4.0中执行此操作,但在此之前,您需要找到另一种方式(可能是ArrayList)。

答案 1 :(得分:1)

是的,这不起作用,代表是完全不相关的类型。通常,泛型类型只有System.Object作为公共基类型。但是在这里,因为他们是代表,你可以将它们存储在List<Delegate>中。我怀疑这会帮助你让他们取消注册。但我无法真正想象代码可能是什么样的。

答案 2 :(得分:0)

通用委托声明可以指定某些类型参数应该是协变的或逆变的,这将允许您所遵循的分配类型。遗憾的是,多播委托的内部实现使得不可能组合不同类型的委托(“简单”委托保存有关其类型的信息,以及方法指针和对其目标的引用;多播委托关于其类型的委托信息以及保存每个组成委托的方法指针和目标引用,但不保留对已合并的原始委托的任何引用,也不保存有关其类型的任何信息)。因此,尝试将EventHandler<DerivedEventArgs>EventHandler<EventArgs>合并将在运行时失败。

如果EventHandler<T>T相反,则尝试将EventHandler<EventArgs>传递给期望AddHandler的标准事件EventHandler<DerivedEventArgs>方法,如果没有订阅其他处理程序,甚至会成功,因为EventHandler<EventArgs>Delegate.Combinenull,因此作为EventHandler<EventArgs>存储在事件的委托字段中。不幸的是,后续尝试添加EventHandler<DerivedEventArgs>(实际上是预期的类型)会失败,因为它的类型与它所组合的委托不匹配。微软认为这种行为会违反最小惊讶原则(如果通过“错误”代表会导致任何问题,那么当该代表通过时应该这样做,而不是在通过后者时),并决定最小化可能性通过使它成为一个尝试将EventHandler<EventArgs>传递给期望EventHandler<DerivedEventArgs>的处理程序的尝试将失败编译,即使该行为可能成功,如果它是唯一的订阅。