无法将委托强制转换为泛型类型 T
本文关键字:转换 泛型类型 | 更新日期: 2023-09-27 18:34:08
为什么我们不能将委托的实例转换为泛型类型T
?
考虑一个实用程序方法CreateDelegate
,它创建一个 T 实例,它是一个委托,即从 MulticastDelegate
派生的类型。
T CreateDelegate<T>() {… }
不幸的是,泛型不允许将T
约束为派生的类型,MulticastDelegate
给出以下编译错误:
约束不能是特殊类"系统.多播委托">
尽管如此,此实用程序方法正在检查T
是否与MulticastDelegate
兼容,并通过反射通过Delegate::CreateDelegate
创建委托。但是,如果我们尝试将Delegate::CreateDelegate
的结果转换为 T
,我们将得到以下编译错误:
无法将类型"系统.委托"转换为"T">
但是,如果我先将其转换为object
,然后再投射到T
它将正常工作:
T h = (T) ((object) Delegate.CreateDelegate(typeof(T), target, m));
为什么我们不能直接将委托投给 T?
C# 语言强制进行静态检查,从类型 X 到类型 Y 的强制转换是否有效,即编译器可以(在一定程度上(保证兼容性并拒绝编译时明确的错误是否有意义。不受约束的泛型类型T
和System.Delegate
没有任何直接的共同点。然而,当强制转换为object
时,编译器知道每个类型本质上都是一个object
,所以它允许强制转换。这并不意味着运行时类型检查在特定情况下不会失败。
as
运算符更宽松一些,因为它不会导致无效强制转换异常。编译器在应用静态检查方面也不太严格。在您的特定情况下,这很有帮助,因为您可以省略中间转换以object
并使用as T
。但是,需要as
仅适用于类类型,因此您必须应用 where T : class
约束。
因此,该方法将如下所示(简化(:
public T CreateDelegate<T>(…) where T : class
{
return Delegate.CreateDelegate(typeof(T), …) as T;
}
正如@usr建议的那样,推荐阅读的是 Eric Lippert 的博客,例如这篇关于强制转换和类型参数的文章。