Как обычно, int?
означает System.Nullable<int>
(или System.Nullable`1[System.Int32]
).Почему сумма Linq-to-Objects из последовательности нулевых значений сама по себе является нулевой?
Предположим, у вас есть оперативная память IEnumerable<int?>
(например, List<int?>
), назовем ее seq
; то вы можете найти его сумму с:
var seqSum = seq.Sum();
Конечно это идет к перегрузке int? IEnumerable<int?>.Sum()
(documentation) метод расширения, который на самом деле статический метод на 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 */ }
, который в действительности будет недоступен (факт, который компилятор C# не может знать из).
Так почему же этот параметр возврата не просто объявлен как int
без значения NULL?
Интересно, есть ли какие-либо выгоды от того же типа возврата, что и у int? IQueryable<int?>.Sum()
(в классе System.Linq.Queryable
). Этот последний метод может возвращать null
на практике, если есть поставщики LINQ (возможно, LINQ to SQL?), Которые его реализуют.
Я предполагаю, что это продолжение формата 'Sum', возвращающего тот же тип, который вы суммируете. В конечном итоге только один из разработчиков C# может ответить на это. – juharr
Совместимость с 'Queryable' - это единственное, о чем я могу думать. Вы имеете право сказать, что он никогда не возвращает «null»: https://github.com/dotnet/corefx/blob/master/src/System.Linq/src/System/Linq/Sum.cs –
@HimBromBeere нет перегрузка формы 'Sum (этот IEnumerable источник)'; API-интерфейсы * generic * также принимают * селектор * формы 'Func ' и т. д. –