2010-09-09 4 views
8

Quelqu'un peut-il expliquer ce qui se passe ici? Comment à la fois ces choses sont vraies?LINQ Comportement d'agrégation des types à valeurs nulles

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

Spécifiquement, pourquoi la méthode Sum() ne retourne pas 'null'? Ou le singleSum n'est pas égal à 17?

+0

+1 Question intéressante! –

Répondre

4

Ce que vous voyez est la différence entre l'utilisation de Enumerable.Sum et l'ajout de valeurs vous-même.

La chose importante ici est le null n'est pas zéro. À première vue, vous penseriez que singleSumdevrait égale 17 mais cela signifierait que nous devrions assigner des sémantiques différentes à null en fonction du type de données de la référence. Le fait qu'il s'agisse d'un int? ne fait aucune différence - null est null et ne devrait jamais être sémantiquement égal à la constante numérique 0.

L'implémentation de Enumerable.Sum est conçue pour ignorer toute valeur null dans la séquence. C'est la raison pour laquelle vous constatez le comportement différent entre les deux tests. Cependant, le deuxième test renvoie correctement null car le compilateur est suffisamment intelligent pour savoir que l'ajout de null donne null.

Voici la mise en œuvre de Enumerable.Sum qui accepte un paramètre de 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); 
} 
+0

Je comprends tout à fait pourquoi singelSum est nul, pas 17 - parce que null est juste nul ... entièrement avec vous là :) Je suppose que ma question était plus, comment Sum() n'a pas retourné null, aussi ... – kiwipom

6

La méthode .Sum() de types nullables ignore toutes les valeurs null:

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

Remarques

Le résultat ne comprend pas des valeurs qui sont nulles.

Alors que si vous ajoutez un nombre via + à null le résultat est null.

Comme Andrew Hare a noté, il n'a pas de sens d'ajouter un numéro à null: null n'est pas 0; ce n'est juste pas un nombre.

+0

merci pour le lien ... on dirait que c'est comme ça que ça fonctionne. Je reçois cela maintenant - acclamations :) – kiwipom

+0

vraiment désolé je ne pouvais pas marquer ces deux réponses comme correctes ... +1 de moi, de toute façon! merci – kiwipom