我不熟悉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”?或者还有某种我想念的“额外的编译时检查”?
答案 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所说,它使您能够使用相同的语法处理可空类型和引用类型。