考虑以下:
var emptyValueList = new List(); //any value type (long, float, any struct ...) var minimum = emptyValueList.Min();
这将抛出InvalidOperationException
(Sequence不包含任何元素).
现在让我们尝试使用引用类型:
var emptyReferenceList = new List
这不会抛出并返回null
.就好像default
第二种情况要求操作员,而第一种情况则不然.它也适用于可空类型(例如int?
,即使它们是值类型).
我想知道为什么会这样,如果背后有一个具体的推理?
这是一个设计决定,我们将不得不向BCL的作者询问.
Min
扩展方法有各种重载.对于允许的类型null
,我相信在搜索最小值时会Min
跳过所有null
值.这适用于引用类型和类型Nullable<>
(在您的示例中Nullable
),它不是引用类型,但允许null
(Min
方法决定忽略).
因此,对于不可为空的结构,作者Min
可能认为返回是"危险的",default(TSource)
因为在其他情况下(通常是数字0
),这可能是有意义的(即非空)最小值,因此输出可能被误解.
对于允许的类型null
,因为作者选择跳过null
从源产生的值,可以安全地假设null
只有在序列除了包含null
值(包括en empty source的情况)时才返回.
请注意,在IComparer<>
可空类型或引用类型的标准下,该null
值小于任何非空值.对于排序算法(如所使用的算法List<>.Sort
),订单必须是完全的和可传递的.因此,我们得到:
Console.WriteLine( Comparer.Default.Compare(null, 7) ); // "-1" Console.WriteLine( Nullable.Compare((int?)null, 7) ); // "-1" Console.WriteLine( new List { 9, null, 7, 13, } .OrderBy(ni => ni).First() ); // "" // 'Min' is special in that it disregards 'null' values Console.WriteLine( new List { 9, null, 7, 13, } .Min() ); // "7"
和Min
适用于真正的参考类型相同的方式,例如System.Version
(这是一种class
类型):
var li = new List{ new Version("9.0"), null, new Version("7.0"), new Version("13.0"), }; Console.WriteLine(li.OrderBy(ve => ve).First()); Console.WriteLine(li.Min());