2012-02-05 48 views
0

我新在C#泛型和一边看书时的例子偶然发现:使用仿制药,而不是铸造的AsEnumerable

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

@DBM,'car'不是'IEnumerable ',它是'T'。 – svick 2012-02-05 23:14:11

+0

啊,你说得对。我很累...... T可能是一个'DataRow' – 2012-02-05 23:15:20

回答

2

它不会给你任何额外的编译时检查。如果你使用了错误的类型,在这两种情况下你都会在运行时遇到异常。

但是,执行简单转换无法执行的其他内容可能很有用。例如Field<int>("CarId")可能会调用将该字段中的string转换为int的方法。

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

0

编译器不知道,您指定的字段“颜色”是字符串类型。在内部,Field<T>()方法实现这一点很神奇。

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

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

0

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

在你的榜样,如果“颜色”字段的值为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"]; 

Field<T>另一个好处是,作为svick笔记,它使您能够使用相同的语法使用可空类型和引用类型。