简体   繁体   English

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

[英]Using generics instead of casting for AsEnumerable

I am new to generics in C# and while reading a book stumbled upon an example: 我不熟悉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")
    };

The author says that car.Field<string>("Color") gives the additional compile-time checking comparing to (string)car["Color"] . 作者说car.Field<string>("Color")给出了与(string)car["Color"]相比较的额外编译时检查。 But how does the compiler know that car.Field<string>("Color") is compilable for "Color" and not for "CarID"? 但编译器如何知道car.Field<string>("Color")可编译为“Color”而不是“CarID”? Or there is some kind of another "additional compile-time checking" that I miss? 还是有一些我想念的“额外的编译时检查”?

It doesn't give you any additional compile-time checking. 它不会为您提供任何额外的编译时检查。 If you use the wrong type, in both cases you'll get an exception during run-time. 如果使用错误的类型,在这两种情况下,您将在运行时获得异常。

But it can be useful to do additional stuff that simple cast can't. 但是做一些简单的演员不能做的额外的事情会很有用。 For example Field<int>("CarId") could call a method that converts the string in the field to an int . 例如, Field<int>("CarId")可以调用一个方法,将字段中的string转换为int

And assuming you're talking about DataRow.Field<T>() , then, according to the documentation, it's useful mostly for dealing with null values and nullable types correctly. 假设您正在讨论DataRow.Field<T>() ,那么,根据文档,它主要用于正确处理null值和可空类型。

The compiler doesn't know, your specifying that field "Color" is of type string. 编译器不知道,您指定字段“Color”是字符串类型。 Internally, the Field<T>() method does it's magic to make that happen. 在内部, Field<T>()方法可以实现这一点。

If you perform a cast ( (string)car["Color"] ) you could encounter a runtime exception if the field value cannot be converted to the destination type. 如果执行强制转换( (string)car["Color"] ),如果字段值无法转换为目标类型,则可能会遇到运行时异常。

From memory, if you specify car.Field<string>("ColorID") , you will be able to safely convert int to string without any issues. 从内存中,如果指定car.Field<string>("ColorID") ,您将能够安全地将int转换为字符串而不会出现任何问题。

Specifically, the real benefit of car.Field<string>("Color") is that it encapsulates testing field values for equality with DBNull.Value , making your code cleaner and easier to read. 具体来说, car.Field<string>("Color")的真正好处是它使用DBNull.Value封装测试字段值,使代码更清晰,更易于阅读。

In your example, if the value of the "Color" field is null, the Field<T> extension method will return null , while car["Color"] will return DBNull.Value . 在您的示例中,如果“Color”字段的值为null,则Field<T>扩展方法将返回null ,而car["Color"]将返回DBNull.Value You can't cast DBNull.Value to string , so the expression (string)car["Color"] raises an InvalidCastException in that case. 您不能将DBNull.Value InvalidCastExceptionstring ,因此表达式(string)car["Color"]在这种情况下会引发InvalidCastException

Before the development of the DataSetExtensions class, you would need a somewhat verbose expression to assign the value of that field to a string variable: 在开发DataSetExtensions类之前,您需要一个有点冗长的表达式来将该字段的值赋给string变量:

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

Another benefit of Field<T> is, as svick notes, that it enables you to work with nullable types and reference types using the same syntax. 正如svick所说, Field<T>另一个好处是,它使您能够使用相同的语法处理可空类型和引用类型。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM