2012-02-05 3 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") скомпилирован для «Цвет», а не для «CarID»? Или есть какая-то еще «дополнительная проверка времени компиляции», которую я пропускаю?

+0

@DBM, 'car' не является' IEnumerable ', это' T'. – svick

+0

Ах, ты прав. Я устал ... T может быть «DataRow» –

ответ

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, что делает ваш код более чистым и понятным для чтения.

В вашем примере, если значение поля «Color» имеет нулевое значение, метод 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 примечаниями, что он позволяет работать с типами NULL и ссылочными типами с использованием того же синтаксиса.

Смежные вопросы