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);