C# 为什么在引用的空列表上调用Min()不会引发错误?

C# 为什么在引用的空列表上调用Min()不会引发错误?,c#,ienumerable,value-type,reference-type,C#,Ienumerable,Value Type,Reference Type,考虑以下几点: var emptyValueList = new List<int>(); //any value type (long, float, any struct ...) var minimum = emptyValueList.Min(); 这不会抛出并返回null。就好像第二种情况调用了default操作符,但第一种情况没有调用。它也适用于可为空的类型(例如,int?,即使它们是值类型) 我想知道为什么会出现这种情况,以及这背后是否有具体的原因?这是一个设计决策,

考虑以下几点:

var emptyValueList = new List<int>(); //any value type (long, float, any struct ...)
var minimum = emptyValueList.Min();
这不会抛出并返回
null
。就好像第二种情况调用了
default
操作符,但第一种情况没有调用。它也适用于可为空的类型(例如,
int?
,即使它们是值类型)


我想知道为什么会出现这种情况,以及这背后是否有具体的原因?

这是一个设计决策,我们必须询问BCL的作者

有各种类型的重载。对于允许
null
的类型,我相信
Min
在搜索最小值时会跳过所有
null
值。这适用于引用类型和(在您的示例中为
null
),后者不是引用类型,但允许
null
(由
Min
方法决定忽略)

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

对于允许
null
的类型,由于作者选择跳过从源代码生成的
null
值,因此可以安全地假设只有当序列只包含
null
值(包括en empty source的情况)时才会返回
null


请注意,在可空类型或引用类型的标准
IComparer
下,
null
值小于任何非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"

你也可以考虑使用扩展:

using System.Linq;
public static class EnumerableExtensions {

    public static X MinOrDefault<T, X>(this IEnumerable<T> that, Func<T, X> minXp, X defaultValue) {
        if (that.Any())
            return that.Min(minXp);
        else
            return defaultValue;
    }
}

...

var emptyValueList = new List<int>();
var minimum = emptyValueList.MinOrDefault(e => e, 0);

var emptyEmployeeList = new List<Employee>();
var minimumSalary = emptyEmployeeList.MinOrDefault(e => e.Salary, 0);
使用System.Linq;
公共静态类EnumerableExtensions{
公共静态X MinOrDefault(此IEnumerable that,Func minXp,X defaultValue){
如果(that.Any())
返回该.Min(minXp);
其他的
返回默认值;
}
}
...
var emptyValueList=新列表();
var minimum=emptyValueList.MinOrDefault(e=>e,0);
var emptyEmployeeList=新列表();
var minimumSalary=emptyEmployeeList.MinOrDefault(e=>e.Salary,0);

newlist();智力?这意味着它是可空的,这就是它没有抛出任何错误的原因。当然,不令人满意的答案是,这就是那些函数记录的有趣之处,它们不知道
Min
(和
Max
)的特殊行为。听起来像是在计算各自的sql聚合函数。
  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());
using System.Linq;
public static class EnumerableExtensions {

    public static X MinOrDefault<T, X>(this IEnumerable<T> that, Func<T, X> minXp, X defaultValue) {
        if (that.Any())
            return that.Min(minXp);
        else
            return defaultValue;
    }
}

...

var emptyValueList = new List<int>();
var minimum = emptyValueList.MinOrDefault(e => e, 0);

var emptyEmployeeList = new List<Employee>();
var minimumSalary = emptyEmployeeList.MinOrDefault(e => e.Salary, 0);