[英]Using parameter of generic class as type of event
class MyClass<T> {
public event T MyEvent;
}
错误: CS0066 'MyClass<T>.MyEvent': event must be of a delegate type
。
好的... C# ≥7.3 允许Delegate
作为基类约束。 让我们使用它:
class MyClass<T> where T: Delegate {
public event T MyEvent;
}
错误: CS0066 'MyClass<T>.MyEvent': event must be of a delegate type
。
什么???
尽管我在 C# 规范中找不到记录在案的限制,但我可以看到在 C#/CLR 中支持此类事件至少存在两个问题,这两个问题都与它的引发方式有关。
C# 只允许从声明它的类型中引发事件。 但是,如果您的泛型类甚至不知道它T
的参数数量,那么引发事件的代码应该是什么样的?
class MyClass<T> where T: Delegate
{
public event T MyEvent;
public void DoSomething()
{
// raise MyEvent here
MyEvent(/* what goes here? */);
}
}
当然,您可以使MyClass
抽象并说指定T
类型的继承者将引发事件。 然而,在我看来,这将是一种非常不一致的语言设计。
CLR 实现运行时泛型。 这意味着,编译器必须为满足通用约束的任何T
生成在运行时应该很好的 IL。
引发事件基本上是调用存储在事件字段中的委托。 编译器应生成大致包括以下步骤的 IL:
如果委托不是void
,则需要额外的步骤:
如您所见,生成的 IL 严格取决于参数的数量以及委托是否为void
。 因此,这种 IL 对任何Delegate
都没有好处。
具有通用参数的事件委托是完全可以的,例如:
delegate void MyEventHandler<K, V>(K key, V value);
因为参数的数量以及委托是否为void
在编译时是已知的。 在这种情况下,可以生成适用于任何K
和V
的同一组 IL 指令。 在 IL 中, K
和V
作为类型占位符生成,CLR 能够在运行时解析它们。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.