假设你有一个内存中的IEnumerable< int?> (例如List< int?>例如),让我们称之为seq;那么你可以找到它的和:
var seqSum = seq.Sum();
当然,这是扩展方法重载int? IEnumerable<int?>.Sum()
(documentation),这是System.Linq.Enumerable上的静态方法.
但是,该方法从不返回null,所以为什么返回类型被声明为Nullable?即使在seq是空集合的情况下,或更一般地,集合的所有元素都是类型为int的空值,则所述的Sum方法仍然返回零,而不是null.
这从文档中可以看出,也可以来自System.Core.dll源代码:
public static int? Sum(this IEnumerable<int?> source) { if (source == null) throw Error.ArgumentNull("source"); int sum = 0; checked { foreach (int? v in source) { if (v != null) sum += v.GetValueOrDefault(); } } return sum; }
请注意,只有一个返回语句,其表达式和具有int类型(然后将隐式地通过换行转换为int?).
总是包装返回值似乎很浪费. (如果需要的话,呼叫者可以总是在他身边隐含地进行包装)
此外,这种返回类型可能会导致调用者编写代码,如if(!seqSum.HasValue){/ *逻辑来处理这个* /},这实际上是不可达到的(C#编译器不知道的事实).
那么为什么这个返回参数不会简单地声明为int,不能为空?
我想知道是否有与int? IQueryable<int?>.Sum()
(在System.Linq.Queryable类中)具有相同返回类型的任何好处.如果有LINQ提供程序(也许LINQ to sql?)实现它,后一种方法在实践中可能返回null.
解决方法
如果您查看System.Linq.Enumerable的其余部分,特别是数学相关函数,您将开始看到一种具有返回与输入参数相同类型的趋势的模式,除非返回值具有特定的原因不同的类型
请参阅以下功能:
MAX():
public static int Max(this IEnumerable<int> source); public static int? Max(this IEnumerable<int?> source); public static long Max(this IEnumerable<long> source); public static long? Max(this IEnumerable<long?> source);
MIN():
public static int Min(this IEnumerable<int> source); public static int? Min(this IEnumerable<int?> source); public static long Min(this IEnumerable<long> source); public static long? Min(this IEnumerable<long?> source);
和():
public static int Sum(this IEnumerable<int> source); public static int? Sum(this IEnumerable<int?> source); public static long Sum(this IEnumerable<long> source); public static long? Sum(this IEnumerable<long?> source);
对于规则的例外,请查看平均值…
public static double Average(this IEnumerable<int> source); public static double? Average(this IEnumerable<int?> source);
你可以看到它仍然保留了Nullable T类型,但返回类型必须被更改为合适的类型,以支持平均整数一起产生的结果.
当您进一步了解Average时,您会看到以下内容:
public static float Average(this IEnumerable<float> source); public static float? Average(this IEnumerable<float?> source);
再次,回到与原始传入类型返回相同类型的默认模式.
现在我们在这里看到这个模式,我们来看看我们是否看到其他地方,让我们来看看System.Math,因为我们在这个问题上.
再次,这里我们看到使用相同返回类型的相同模式:
public static int Abs(int value); public static long Abs(long value); public static int Max(int val1,int val2); public static long Max(long val1,long val2);
我会再提一次,这是相当于一个“意见回答”.我已经看过了,可能在这是为MS备份我的分析语言模式暗示任何MS最佳做法或语言规范信息,但我无法找到任何东西.话虽如此,如果您查看.Net核心库中的各种位置,特别是System.Collections.Generic命名空间,您将看到除非有特定的原因,否则返回类型与集合类型相匹配.
我认为没有理由将这个规则从Nullable< T>类型.