泛型和铸造

时间:2010-10-29 10:46:34

标签: c# generics

为什么以下编译?

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 ... }

3 个答案:

答案 0 :(得分:20)

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

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

你可以很容易地解决它:

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

这很难看,但它应该有用......至少在这种情况下它不会造成任何拳击。

答案 1 :(得分:0)

C#4.0允许在参数化接口和委托类型上声明协方差和逆变。

答案 2 :(得分:0)

如果替换

会发生什么

return (MyClass<T>)

return (MyClass<bool>)