That is a design decision that we will have to ask the authors of the BCL about.
There are various overloads of the Min
extension method. For types that allow null
, I believe Min
skips all null
values when searching for the minimum. This goes for both reference types and the type Nullable<>
(in your example Nullable<int>
) which is not a reference type, but which allows null
(that the Min
methods decide to disregard).
So with non-nullable structs, the authors of Min
probably thought it would be "dangerous" to return default(TSource)
since that could be a meaningfull (i.e. non-null) minimum in other cases (often the number 0
), and hence the output could be misunderstood.
With types that allow null
, because the authors chose to skip null
values yielded from the source, one can safely assume that null
is returned only if the sequence contains nothing but null
values (including the case of en empty source).
Note that under the standard IComparer<>
for nullable types or reference types, the null
value is less than any non-null value. For sorting algorithms (like the one used by List<>.Sort
) the order must be total and transitive. We therefore get:
Console.WriteLine(
Comparer<int?>.Default.Compare(null, 7)
); // "-1"
Console.WriteLine(
Nullable.Compare((int?)null, 7)
); // "-1"
Console.WriteLine(
new List<int?> { 9, null, 7, 13, }
.OrderBy(ni => ni).First()
); // ""
// 'Min' is special in that it disregards 'null' values
Console.WriteLine(
new List<int?> { 9, null, 7, 13, }
.Min()
); // "7"
And Min
works the same way for true reference types, for example System.Version
(which is a class
type):
var li = new List<Version> { new Version("9.0"), null, new Version("7.0"), new Version("13.0"), };
Console.WriteLine(li.OrderBy(ve => ve).First());
Console.WriteLine(li.Min());