使用泛型而不是为AsEnumerable进行强制转换

时间:2012-02-05 23:05:34

标签: c# linq generics

我不熟悉C#中的泛型,在阅读一本书时偶然发现了一个例子:

var cars = from car in data.AsEnumerable()
  where
    car.Field<string>("Color") == "Red"
    select new
    {
      ID = car.Field<int>("CarID"),
      Make = car.Field<string>("Make")
    };

作者说,与car.Field<string>("Color")相比,(string)car["Color"]提供了额外的编译时检查。但编译器如何知道car.Field<string>("Color")可编译为“Color”而不是“CarID”?或者还有某种我想念的“额外的编译时检查”?

3 个答案:

答案 0 :(得分:2)

它不会为您提供任何额外的编译时检查。如果使用了错误的类型,在这两种情况下,您将在运行时获得异常。

但是做一些简单的演员不能做的事情会很有用。例如,Field<int>("CarId")可以调用将字段中的string转换为int的方法。

假设您正在讨论DataRow.Field<T>(),那么根据文档,它主要用于正确处理null值和可空类型。

答案 1 :(得分:0)

编译器不知道,你指定字段“Color”是string类型。在内部,Field<T>()方法可以实现这一目标。

如果执行强制转换((string)car["Color"]),如果无法将字段值转换为目标类型,则可能会遇到运行时异常。

从内存中,如果指定car.Field<string>("ColorID"),您将能够安全地将int转换为字符串而不会出现任何问题。

答案 2 :(得分:0)

具体来说,car.Field<string>("Color")的真正好处是它将测试字段值封装为与DBNull.Value相等,使您的代码更清晰,更易于阅读。

在您的示例中,如果“颜色”字段的值为空,则Field<T>扩展方法将返回null,而car["Color"]将返回DBNull.Value。您无法将DBNull.Value投射到string,因此在这种情况下,(string)car["Color"]表达式会引发InvalidCastException

在开发DataSetExtensions类之前,您需要一个有点冗长的表达式来将该字段的值赋给string变量:

var color = DBNull.Value.Equals(car["Color"]) ? null : (string)car["Color"];

Field<T>的另一个好处是,正如svick所说,它使您能够使用相同的语法处理可空类型和引用类型。