将对象转换为通用类型的方法

7

关于“强制将泛型类型转换为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编译器错误的方法。

但是为什么在使用object as T时需要where T : class而在使用(T)object时不需要呢? 这两种方式的对象转换实际上有什么区别?


哦,是的,谢谢abatishchev。没有命名空间更整洁 :) - Heki
4个回答

18

由于as暗示强制转换可能失败并返回null。没有:classT可以是int等类型,这些类型不能为null。使用(T)obj将会导致它简单地爆炸成火花雨; 不需要处理null

顺便提一下(re struct),请注意如果已知您正在转换为一个Nullable<>,则可以使用as - 例如:

static T? Cast<T>(object obj) where T : struct
{
    return obj as T?;
}

非常有用的信息。我会接受你的答案,但系统告诉我要等八分钟。 - Heki
MSDN文档可以在这里找到:http://msdn.microsoft.com/en-us/library/cscsdfbt(v=VS.100).aspx(供进一步阅读) - Jonas Van der Aa

2
使用"as"进行类型转换时,如果可以进行转换,则执行转换;如果不能进行转换,则返回null。这在未受限制的泛型参数(第二个示例)中存在问题,因为T可能是值类型(如int),该类型的变量无法保存null
当您的泛型参数被限制为引用类型(使用class约束)时,编译器可以更好地推断出您的类型,并理解null将始终是类型T的有效值。因此,可以安全地使用"as"风格的类型转换。

1

(T)obj 如果 obj 无法转换为 T, 将会抛出异常。如果你确定转换一定会成功,你应该使用 (T)obj

当需要将一个类型转换为另外一个类型时,可以使用 as 替代先用 is 检查再进行强制转换的方式。当转换失败时,as 返回 null。需要注意的是,T 需要是可空类型(任意引用类型或者是 Nullable<T>)。典型的模式如下:

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

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

注意:由于Deserialize返回的是object,其他转换方式都不适用。 - Marc Gravell
是的,在这种情况下,他无论如何都应该使用(T)x强制转换,因为他知道结果是T类型。 - CodesInChaos

1

关于运算符 as 在失败的情况下返回 null,变量应该是一个类或可空结构体:

同时,cast 不需要这样的限制,你可以将结构体转换为另一个结构体。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接