与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
?
两种铸造物体的方式之间的实际差异是什么?
答案 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
仅适用于转化的子集。重载的强制转换等将被忽略。