将对象转换为泛型类型的方法

时间:2010-12-21 08:39:14

标签: c# generics casting

Casting generic type "as T" whilst enforcing the type of T

有关

使用以下示例

private static T deserialize<T>(string streng) where T : class
{
    XmlSerializer ser = new XmlSerializer(typeof(T));
    StringReader reader = new StringReader(streng);
    return ser.Deserialize(reader) as T;
}

private static T deserialize<T>(string streng)
{
    XmlSerializer ser = new XmlSerializer(typeof(T));
    StringReader reader = new StringReader(streng);
    return (T)ser.Deserialize(reader);
}

我习惯于进行object as Type投射,所以当我发现我不能用T这样做时,我有点困惑。然后我找到了上面的问题,并找到了as T编译器错误的解决方案。

但是,使用where T : class而使用object as T时,为什么需要(T)object? 两种铸造物体的方式之间的实际差异是什么?

4 个答案:

答案 0 :(得分:18)

因为as意味着强制转换可能会失败并返回null 。如果没有: class,则T可以是int等 - 不能是null(T)obj null只会在一阵火花中爆炸;无需处理struct

作为旁边(重新as),请注意,可以使用Nullable<>,如果知道您要投放到static T? Cast<T>(object obj) where T : struct { return obj as T?; } - 例如:< / p>

{{1}}

答案 1 :(得分:2)

使用“as”进行投射指定为1)如果可以,则执行强制转换; 2)如果不能则返回null。对于无约束的泛型参数(第二个示例),这是有问题的,因为T可能是值类型(如int),其变量不能容纳null

当您的泛型参数被约束为引用类型(具有class约束)时,编译器可以更多地推断您的类型并理解null将始终是有效值类型T.因此,可以安全地使用“as”式演员表。

答案 2 :(得分:1)

就失败情况而言,运算符as返回null,变量应该是一个类或可为空的结构:

同时cast不需要这样,你可以在struct上转换struct。

答案 3 :(得分:1)

如果(T)obj无法转换为obj

T会抛出。如果您确定转换有效,则应使用(T)obj

并使用as将测试替换为is,然后使用强制转换。当然,T需要可以为空(引用类型或Nullable<T>),因为as在失败时返回null。典型的模式是:

T x=y as T;
if(x!=null)
  DoSomething(x);

另一个区别是as仅适用于转化的子集。重载的强制转换等将被忽略。