LINQ可空类型的聚合行为

kiw*_*pom 8 .net linq nullable

有人能解释一下这里发生了什么吗?Howcome 两种这些东西是真的吗?

[TestMethod]
public void WhatIsGoingOnHere()
{
    List<int?> list = new List<int?> { 1, 2, 3, null, 5, 6 };
    Assert.AreEqual(17, list.Sum());

    int? singleSum = 1 + 2 + 3 + null + 5 + 6;

    Assert.IsNull(singleSum);
}
Run Code Online (Sandbox Code Playgroud)

具体来说,为什么Sum()方法不返回'null'?或者单身不等于17?

Nul*_*ion 6

.Sum()可空类型的方法忽略所有null值:

MSDN: Enumerable.Sum Method (IEnumerable<Nullable<Int32>>)

备注

结果不包含null值.

而如果您是通过添加任何数量+null结果null.

正如Andrew Hare指出的那样,添加一个数字是没有意义的null:null不是0; 这不是一个数字.


And*_*are 4

Enumerable.Sum您所看到的是使用这些值和自己实际添加这些值之间的区别。

这里重要的是null不为零。乍一看,您可能会认为它singleSum 应该等于 17,但这意味着我们必须null根据引用的数据类型分配不同的语义。事实上,这是一个int?没有什么区别——nullnull语义上不应该与数字常量相等0

的实现Enumerable.Sum旨在跳过null序列中的任何值,这就是您看到两个测试之间不同行为的原因。然而,第二个测试正确返回,null因为编译器足够聪明,知道添加任何内容都会null产生null.

Enumerable.Sum这是接受参数的实现int?

public static int? Sum(this IEnumerable<int?> source)
{
    if (source == null)
    {
        throw Error.ArgumentNull("source");
    }
    int num = 0;
    foreach (int? nullable in source)
    {
        // As you can see here it is explicitly designed to
        // skip over any null values
        if (nullable.HasValue)
        {
            num += nullable.GetValueOrDefault();
        }
    }
    return new int?(num);
}
Run Code Online (Sandbox Code Playgroud)