Microsoft Developer Network > Forums Home > Archived Forums Forums > LINQ Project General > Why Sum over Nullable return Nullable in same time as Min over real values throw exceptions for empty collections ?
Ask a questionAsk a question
 

AnswerWhy Sum over Nullable return Nullable in same time as Min over real values throw exceptions for empty collections ?

  • Sunday, September 18, 2005 11:47 PMTAG Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     

    This is two related questions:

    a) Why Sum over  int?  return nullable int?  not a regular ?

    In this example

    int? a = null;

    int? b = 1;

    var check = a+b; // Result in null

    int?[] numbers = { a, b};

    var numSum = numbers.Sum();  // Result in 1

    Value of numSum  is 1 - but value of check is null. 

    What is a reason to return nullable int in case if null-value never expected ?

     

    b)  Why it was decided to throw EmptySequenceException for some of agreegate operators like a  Min(this IEnumerable<long> source)  but not for their friends IEnumerable< Nullable<long> >  ?

    int?[] numbers = {};

    var numSum = numbers.Min(); // Result in null

    int[] numbers2 = {};

    var numSum2 = numbers2.Min(); // Result in costly exception

    Why such a difference ? Why not return Nullable<long> in both situations or throw exception in both ?

     

    So - can somebody clarify how it was decided to use Nullable return values for LINQ functions ?

Answers

  • Tuesday, September 20, 2005 4:40 AMAnders Hejlsberg Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer
    Actually, I misspoke on (a) above. Sum ignores null values in the source sequence, but it never returns null. If a sequence is empty or contains only nulls, the result is zero. We could in theory return int from Sum(IEnumerable<int?>), but it would break with the pattern of returning the same type as the element type of the sequence.

    Anders

All Replies

  • Tuesday, September 20, 2005 4:06 AMAnders Hejlsberg Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     

    Regarding (a), the reason Sum(IEnumerable<int?>) returns int? (and not int) is that the result is null if the source is empty or contains only nulls.

    Regarding (b), if the source is an enumerable of a non-nullable type, it seems appropriate for the result to also be a non-nullable type. You can always use the Min, Max, or Average method with a lambda argument to produce a sequence of a nullable type and a nullable result. For example:

    int[] numbers = { 1, 2, 3, 4, 5 };
    int? minNum = numbers.Min(x => (int?)x);

    Anders

  • Tuesday, September 20, 2005 4:40 AMAnders Hejlsberg Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer
    Actually, I misspoke on (a) above. Sum ignores null values in the source sequence, but it never returns null. If a sequence is empty or contains only nulls, the result is zero. We could in theory return int from Sum(IEnumerable<int?>), but it would break with the pattern of returning the same type as the element type of the sequence.

    Anders
  • Tuesday, September 20, 2005 12:38 PMTAG Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     

    Hmm..  What is a reason for such a filtering ?  This is inconsistent - as Sum(a,b) != a + b   as well there is no way to figure out if sequence is empty (your trick with  x => (int?)x) does not work - all that we can get is exception or 0 value.
    Current filtering can easily done with   Where(x => x!=null).Sum(). 

    My proposal is to:
    Sum(IEnumerable<int> x)  to return  int?  , null-value will indicate empty sequence. 
    Sum(IEnumerable<int?> x) to return int?  as sum of values or null in case if there no any element or at least one nullable is inside.

    This will make it possible to use thouse operators inside nested queries. At the moment this is risky as this can result in exceptions.

    I do not know high-level design goals - so my idea can be flawed. But it's definitely valuable - as current implementations can be obtained easily    (int) Sum(IE..<int>)  and Where(x => x!=null).Sum()??0   while others options are allowed.