为什么我们不能将委托的实例强制转换为通用类型T
?
考虑一个实用程序方法CreateDelegate
,它创建一个T实例,它是一个委托,即从MulticastDelegate
派生的类型。
T CreateDelegate<T>() {… }
不幸的是,泛型不允许将T
约束到从MulticastDelegate
派生的类型,从而产生以下编译错误:
约束不能是特殊类'System.MulticastDelegate'
然而,此实用程序方法检查T
是否与MulticastDelegate
兼容,并通过Delegate::CreateDelegate
反射创建代理。但是,如果我们尝试将Delegate::CreateDelegate
的结果转换为T
,我们将收到以下编译错误:
无法将类型'System.Delegate'转换为'T'
但是,如果我先将其投放到object
然后投放到T
,它会正常工作:
T h = (T) ((object) Delegate.CreateDelegate(typeof(T), target, m));
为什么我们不能直接将代表委托给T?
1 个答案:
答案 0 :(得分:10)
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的博客,例如: this article on casts and type parameters
出处:https://www.thinbug.com/q/35321586
==================================================================
个人总结,判断泛型是否为delegate类型
我们根据自己代码的情况进行判断,主要是依据运算符 is、as 、IsSubclassOf、IsAssignableFrom等,具体的可以看我前面的相关文章的介绍。
例如:
private static T GetMethodDelegate<T>() where T : class { T res = default(T); Type delegateType = typeof(T); bool isDelegateType = delegateType is Delegate; var s1 = delegateType.IsAssignableFrom(typeof(Delegate)); var s2 = typeof(Delegate).IsAssignableFrom(delegateType); var s3 = typeof(Delegate).IsSubclassOf(delegateType); var s4 = delegateType.IsSubclassOf(typeof(Delegate)); if (isDelegateType) { DynamicMethod dynamicSpeakWithCall = new DynamicMethod("D", null, new[] { typeof(int) });//res = dynamicSpeakWithCall.CreateDelegate(typeof(T)) as T; } return res; }
标签:delegate,委托,delegateType,object,CreateDelegate,typeof,为泛,类型,Delegate From: https://www.cnblogs.com/mq0036/p/16839788.html