为AsEnumerable使用泛型而不是强制转换
本文关键字:转换 AsEnumerable 泛型 | 更新日期: 2023-09-27 18:22:44
我是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")
};
作者说,与(string)car["Color"]
相比,car.Field<string>("Color")
提供了额外的编译时间检查。但是编译器如何知道car.Field<string>("Color")
可用于"Color"而不可用于"CarID"呢?或者我错过了另一种"额外的编译时检查"?
它不会给您任何额外的编译时检查。如果使用了错误的类型,在这两种情况下,运行时都会出现异常。
但是,做一些简单的铸造所不能做的额外的事情是有用的。例如,Field<int>("CarId")
可以调用将字段中的string
转换为int
的方法。
假设您谈论的是DataRow.Field<T>()
,那么,根据文档,它主要用于正确处理null
值和可为null的类型。
编译器不知道,您指定的字段"Color"是字符串类型。在内部,Field<T>()
方法实现了这一点。
如果执行强制转换((string)car["Color"]
),如果字段值无法转换为目标类型,则可能会遇到运行时异常。
在内存中,如果指定car.Field<string>("ColorID")
,则可以安全地将int转换为字符串,而不会出现任何问题。
具体来说,car.Field<string>("Color")
的真正好处是它封装了与DBNull.Value
相等的测试字段值,使代码更干净、更易于阅读。
在您的示例中,如果"Color"字段的值为null,则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"];
正如svick所指出的,Field<T>
的另一个好处是,它使您能够使用相同的语法处理可为null的类型和引用类型。