[英]Using parameter of generic class as type of event
class MyClass<T> {
public event T MyEvent;
}
Error: CS0066 'MyClass<T>.MyEvent': event must be of a delegate type
.错误:
CS0066 'MyClass<T>.MyEvent': event must be of a delegate type
。
Okay… C# ≥7.3 allows Delegate
as base class constraint .好的... C# ≥7.3 允许
Delegate
作为基类约束。 Let's use that:让我们使用它:
class MyClass<T> where T: Delegate {
public event T MyEvent;
}
Error: CS0066 'MyClass<T>.MyEvent': event must be of a delegate type
.错误:
CS0066 'MyClass<T>.MyEvent': event must be of a delegate type
。
WTH???什么???
Though I can't find a documented limitation in the C# spec, I can see at least two problems with supporting such an event in C#/CLR, both related to how it is raised.尽管我在 C# 规范中找不到记录在案的限制,但我可以看到在 C#/CLR 中支持此类事件至少存在两个问题,这两个问题都与它的引发方式有关。
C# only allows raising an event from within the type that declares it. C# 只允许从声明它的类型中引发事件。 But if your generic class doesn't even know the number of parameters it
T
, what should the code that raises the event look like?但是,如果您的泛型类甚至不知道它
T
的参数数量,那么引发事件的代码应该是什么样的?
class MyClass<T> where T: Delegate
{
public event T MyEvent;
public void DoSomething()
{
// raise MyEvent here
MyEvent(/* what goes here? */);
}
}
Of course, you can make MyClass
abstract and say that inheritors that specify the type of T
would raise the event.当然,您可以使
MyClass
抽象并说指定T
类型的继承者将引发事件。 However, this would be quite an inconsistent language design, to my opinion.然而,在我看来,这将是一种非常不一致的语言设计。
CLR implements runtime generics. CLR 实现运行时泛型。 This means, that compiler must generate IL that should be good at runtime for any
T
that meets the generic constraints.这意味着,编译器必须为满足通用约束的任何
T
生成在运行时应该很好的 IL。
Raising an event is basically invoking a delegate that's stored in the event field.引发事件基本上是调用存储在事件字段中的委托。 The compiler should generate IL that roughly includes these steps:
编译器应生成大致包括以下步骤的 IL:
If the delegate isn't void
, an additional step is required:如果委托不是
void
,则需要额外的步骤:
As you can see, the generated IL strictly depends on the number of arguments and whether the delegate is void
.如您所见,生成的 IL 严格取决于参数的数量以及委托是否为
void
。 Therefore, such IL cannot be good for any Delegate
.因此,这种 IL 对任何
Delegate
都没有好处。
Having event delegate with generic parameters is perfectly OK, such as:具有通用参数的事件委托是完全可以的,例如:
delegate void MyEventHandler<K, V>(K key, V value);
because the number of the parameters and whether the delegate is void
is known at compile time.因为参数的数量以及委托是否为
void
在编译时是已知的。 In this case the same set of IL instructions can be generated that is good for any K
and V
.在这种情况下,可以生成适用于任何
K
和V
的同一组 IL 指令。 In the IL, K
and V
are generated as type placeholders, which CLR is capable of resolving at runtime.在 IL 中,
K
和V
作为类型占位符生成,CLR 能够在运行时解析它们。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.