2010-10-29 86 views
11

为什么下面编译?仿制药和铸造

public IList<T> Deserialize<T>(string xml) 
{    
    if (typeof(T) == typeof(bool)) 
     return (IList<T>)DeserializeBools(xml); 

    return null; 
} 

private static IList<bool> DeserializeBool(string xml) { ... do stuff ... } 

但这并不

public MyClass<T> GetFromDb<T>(string id) 
{ 
    if (typeof(T) == typeof(bool)) 
     return (MyClass<T>)GetBoolValue(id); <-- compiler error here 

    return null; 
} 

private static MyClass<bool> GetBoolValue(string id) { ... do stuff ... } 
+5

什么是编译错误... – 2010-10-29 10:47:40

+0

错误说的是什么? – 2010-10-29 10:49:23

+0

无法投射'MyClass '类型的表达式来键入'MyClass ' – Magpie 2010-10-29 10:49:55

回答

20

更换

return (MyClass<T>)

会发生什么原因的接口工作是任何对象可能实现IList<T>(除非它是已知的实例一个密封的类型,不实现它,我猜) - 所以总是有可能引用类型转换为接口。

在后一种情况下,编译器也不愿意这样做,因为它并没有真正知道T是布尔,尽管以前if语句,所以它不知道MyClass<T>MyClass<bool>之间尝试什么转换。不幸的是,对泛型的有效转换是相当有限的。

你可以很容易解决这个问题:

return (MyClass<T>)(object) GetBoolValue(id); 

这是丑陋的,但它应该工作...至少在这种情况下,它不会导致任何拳击。

+0

它的确如此,谢谢 – Magpie 2010-10-29 10:56:04

0

C#4.0允许协变和逆变的参数接口和委托类型的声明。

+0

这不是试图使用通用方差,而是通用方差不适用于值类型类型参数。 – 2010-10-29 10:52:48

0

,如果你有

return (MyClass<bool>) 
+1

然后它将无法从'MyClass '转换为返回类型所需的'MyClass '。 – 2010-10-29 10:52:08