Как обычно, int?
означает System.Nullable<int>
(или System.Nullable`1[System.Int32]
).
Предположим, что у вас есть встроенная память IEnumerable<int?>
(например, List<int?>
), назовем ее seq
; то вы можете найти его сумму с помощью:
var seqSum = seq.Sum();
Конечно, это относится к перегрузке метода расширения int? IEnumerable<int?>.Sum()
(документация), которая действительно является статическим методом на System.Linq.Enumerable
.
Однако метод никогда не возвращает null
, , поэтому почему тип возврата объявлен как Nullable<>
? Даже в тех случаях, когда seq
представляет собой пустую коллекцию или, в общем, коллекцию, все чьими элементами являются null
значение типа int?
, метод Sum
все еще возвращает ноль, а не null
.
Это видно из документации, но также из исходного кода System.Core.dll:
public static int? Sum(this IEnumerable<int?> source) {
if (source == null) throw Error.ArgumentNull("source");
int sum = 0;
checked {
foreach (int? v in source) {
if (v != null) sum += v.GetValueOrDefault();
}
}
return sum;
}
Обратите внимание, что существует только один оператор return
, и его выражение Sum
имеет тип int
(который затем будет неявно преобразован в int?
путем обертывания).
Кажется расточительным всегда обертывать возвращаемое значение. (При желании вызывающий абонент всегда мог сделать обертку неявно на его стороне.)
Кроме того, этот тип возврата может привести вызывающего пользователя к написанию кода, такого как if (!seqSum.HasValue) { /* logic to handle this */ }
, который в действительности будет недоступен (факт, о котором компилятор С# не может знать).
Итак, почему этот возвращаемый параметр не просто объявлен как int
без значения NULL?
Интересно, есть ли какая-либо выгода от того же типа возврата, что и int? IQueryable<int?>.Sum()
(в классе System.Linq.Queryable
). Этот последний метод может возвращать null
на практике, если есть поставщики LINQ (возможно, LINQ to SQL?), Которые его реализуют.