【问题标题】:Ways to cast objects to a generic type将对象转换为泛型类型的方法
【发布时间】:2010-12-21 08:39:13
【问题描述】:

关于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编译器错误的解决方案。

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

【问题讨论】:

  • 哦,是的,谢谢 abatishchev。没有命名空间会更整洁:)

标签: c# generics casting


【解决方案1】:

因为as 暗示转换可能会失败并返回 null。如果没有: classT 可能是 int 等 - 不能是 null。使用(T)obj,它只会在一阵火花中爆炸;无需处理null

顺便说一句(关于struct),请注意您可以使用as,如果知道您正在投射到Nullable&lt;&gt; - 例如:

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

【讨论】:

【解决方案2】:

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

当您的泛型参数被约束为引用类型(使用class 约束)时,编译器可以对您的类型进行更多推理并理解null 将始终是类型T 的有效值。因此, "as" 风格的演员表可以安全使用。

【讨论】:

    【解决方案3】:

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

    同时cast 不需要类似的东西,你可以在结构上转换结构。

    【讨论】:

      【解决方案4】:

      如果obj 不能转换为T,则(T)obj 抛出。如果您确定转换会成功,您应该使用(T)obj

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

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

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

      【讨论】:

      • 注意:因为Deserialize返回object,所以其他转换无论如何都不适用
      • 是的,在这种情况下,他无论如何都应该使用(T)x演员,因为他知道结果是T类型。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多