2010-09-09 67 views
8

有人可以解释这里发生了什么吗? Howcome 这两个这些事情是真的吗?LINQ可空类型的聚集行为

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

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

+0

+1有趣的问题! – 2010-09-09 04:35:26

回答

4

你所看到的是使用Enumerable.Sum和自己实际添加值之间的差异。

这里重要的是null不为零。乍一看,你会认为 应该等于17,但这意味着我们将不得不根据引用的数据类型分配不同的语义到null。事实上,这是一个int?没有区别 - nullnull,并且不应该在语义上等于数字常数0

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

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

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); 
} 
+0

我完全理解为什么singelSum是null,而不是17--因为null只是null ...完全和你在一起:)我想我的问题更多,Sum()如何不返回null ... – kiwipom 2010-09-09 04:36:48

6

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

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

备注

结果不包括为空值。

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

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

+0

感谢您的链接...看起来它只是它的工作原理。我现在得到 - 干杯:) – kiwipom 2010-09-09 04:37:14

+0

真诚抱歉,我无法将这些答案都标记为正确的... +1,无论如何!谢谢 – kiwipom 2010-09-09 04:42:39