Я регулярно ловлю себя на том, что пишу такие вещи, как
int? min = someQueryable
.Where(x => someCondition)
.Select(x => (int?)x.someNonNullableIntProperty)
.Min();
Это позволяет мне получить null вместо «System.ArgumentNullException: значение не может быть null», когда ничто не соответствует условию. (И я не хочу получать 0
вместо null
.)
Я бы хотел избежать актерского состава. Есть ли какой-то другой способ, который я пропустил?
Сложность заключается в том, что он должен быть достаточно широко используемым, чтобы его изначально понимали (или игнорировали) поставщики linq. (linq-to-entities и linq-to -nhibernate для моих конкретных нужд.)
В противном случае мне пришлось бы добавить некоторые пользовательские расширения AsNullable
к провайдеру linq-to-nh (что требует некоторой работы), и я не знаю, позволяет ли EF (6) это сделать.
Почему я хочу избежать приведения? Приведение может остаться незамеченным во время рефакторинга, а затем вызвать ошибки. И большая часть приведения, которое я вижу в коде, происходит из-за небрежности разработчиков, не пытающихся запомнить, например, что они могут иметь ненулевое значение из .Value
для типов, допускающих значение NULL. (Существует также тернарный случай, такой как someCondition ? someIntProperty : (int?)null
, но оператор "Элвис" ?.
, вероятно, позволит избежать большинства из них; и мы также можем написать default(int?)
, хотя это немного длинно. ?.
можно было бы даже использовать для моего примера запроса, но это не было бы общим решением.)
Попытка new Nullable<int>(x.someNonNullableIntProperty)
как предлагается здесь завершается ошибкой с NotSupportedException
(с NH, не тестировалась с EF). Во всяком случае, мне бы это тоже не подошло. В случае более позднего изменения типа свойства это также может остаться незамеченным из-за неявного преобразования. (И попытка new Nullable(x.someNonNullableIntProperty)
не компилируется, вывод аргумента универсального типа плохо работает с конструкторами.)
Попытка x.someNonNullableIntProperty as int?
(которая по-прежнему является приведением, но в этом случае менее терпима к несоответствию типов, см. здесь) завершается неудачей с ArgumentException
(NH тестировался снова, < sub>Выражение типа «System.Int32» не может использоваться в качестве возвращаемого типа «System.Nullable`1[System.Int32]» (переведено)).
Select
, как в примере, я думаю, что-то можно сделать. Но вообще так делать нельзя. - person Ivan Stoev   schedule 23.03.2016