为什么在空引用列表上调用Min()不会抛出?

Max*_*Max 4 c# ienumerable value-type reference-type

考虑以下:

var emptyValueList = new List<int>(); //any value type (long, float, any struct ...)
var minimum = emptyValueList.Min();
Run Code Online (Sandbox Code Playgroud)

这将抛出InvalidOperationException(Sequence不包含任何元素).

现在让我们尝试使用引用类型:

var emptyReferenceList = new List<object>(); //any ref type will do such as object ...
var minimum = emptyReferenceList.Min();
Run Code Online (Sandbox Code Playgroud)

这不会抛出并返回null.就好像default第二种情况要求操作员,而第一种情况则不然.它也适用于可空类型(例如int?,即使它们是值类型).

我想知道为什么会这样,如果背后有一个具体的推理?

Jep*_*sen 6

这是一个设计决定,我们将不得不向BCL的作者询问.

Min扩展方法有各种重载.对于允许的类型null,我相信在搜索最小值时会Min跳过所有null值.这适用于引用类型和类型Nullable<>(在您的示例中Nullable<int>),它不是引用类型,但允许null(Min方法决定忽略).

因此,对于不可为空的结构,作者Min可能认为返回是"危险的",default(TSource)因为在其他情况下(通常是数字0),这可能是有意义的(即非空)最小值,因此输出可能被误解.

对于允许的类型null,因为作者选择跳过null从源产生的值,可以安全地假设null只有在序列除了包含null值(包括en empty source的情况)时才返回.


请注意,在IComparer<>可空类型或引用类型的标准下,该null值小于任何非空值.对于排序算法(如所使用的算法List<>.Sort),订单必须是完全的和可传递的.因此,我们得到:

  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"
Run Code Online (Sandbox Code Playgroud)

Min适用于真正的参考类型相同的方式,例如System.Version(这是一种class类型):

  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());
Run Code Online (Sandbox Code Playgroud)