Why Sum over Nullable return Nullable in same time as Min over real values throw exceptions for empty collections ?
This is two related questions:
a) Why Sum over int? return nullable int? not a regular ?
In this example
int? a = null; int? b = 1;var check = a+b; // Result in null
int?[] numbers = { a, b};
var numSum = numbers.Sum(); // Result in 1
Value of numSum is 1 - but value of check is null.What is a reason to return nullable int in case if null-value never expected ?
b) Why it was decided to throw EmptySequenceException for some of agreegate operators like a Min(this IEnumerable<long> source) but not for their friends IEnumerable< Nullable<long> > ?
int?[] numbers = {}; var numSum = numbers.Min(); // Result in null int[] numbers2 = {}; var numSum2 = numbers2.Min(); // Result in costly exceptionWhy such a difference ? Why not return Nullable<long> in both situations or throw exception in both ?
So - can somebody clarify how it was decided to use Nullable return values for LINQ functions ?
回答
- Actually, I misspoke on (a) above. Sum ignores null values in the source sequence, but it never returns null. If a sequence is empty or contains only nulls, the result is zero. We could in theory return int from Sum(IEnumerable<int?>), but it would break with the pattern of returning the same type as the element type of the sequence.
Anders
すべての返信
Regarding (a), the reason Sum(IEnumerable<int?>) returns int? (and not int) is that the result is null if the source is empty or contains only nulls.
Regarding (b), if the source is an enumerable of a non-nullable type, it seems appropriate for the result to also be a non-nullable type. You can always use the Min, Max, or Average method with a lambda argument to produce a sequence of a nullable type and a nullable result. For example:
int[] numbers = { 1, 2, 3, 4, 5 };
int? minNum = numbers.Min(x => (int?)x);
Anders- Actually, I misspoke on (a) above. Sum ignores null values in the source sequence, but it never returns null. If a sequence is empty or contains only nulls, the result is zero. We could in theory return int from Sum(IEnumerable<int?>), but it would break with the pattern of returning the same type as the element type of the sequence.
Anders Hmm.. What is a reason for such a filtering ? This is inconsistent - as Sum(a,b) != a + b as well there is no way to figure out if sequence is empty (your trick with x => (int?)x) does not work - all that we can get is exception or 0 value.
Current filtering can easily done with Where(x => x!=null).Sum().
My proposal is to:
Sum(IEnumerable<int> x) to return int? , null-value will indicate empty sequence.
Sum(IEnumerable<int?> x) to return int? as sum of values or null in case if there no any element or at least one nullable is inside.
This will make it possible to use thouse operators inside nested queries. At the moment this is risky as this can result in exceptions.
I do not know high-level design goals - so my idea can be flawed. But it's definitely valuable - as current implementations can be obtained easily (int) Sum(IE..<int>) and Where(x => x!=null).Sum()??0 while others options are allowed.

