0

I have the following where I want to handle null values in a specific way when fetching from db:

    /// <summary>
    /// Implemented this because the Linq Sum() method does not fit our requirements for handling null values:
    /// 1. Empty or null source should return a null, not zero
    /// 2. If non-empty, and all elements are null, then return null, not zero
    /// 3. If non-empty, and some elements are null, ignore them
    public static decimal? NullableSum(this IEnumerable<decimal?> source)
    {
        if (source == null || source.Count() == 0) return null;

        decimal? sum = null;

        foreach (var v in source)
        {
            if (v != null)
            {
                if (sum == null)
                {
                    sum = 0;
                }

                sum += v;
            }
        }

        return sum;
    }

How can I genericize this?

8
  • 2
    So you want it to handle multiple numeric types? Short answer - you can't. Commented Sep 9, 2020 at 1:15
  • 2
    Also, don't do || source.Count() == 0 like that. It causes completely unnecessary double enumeration. It can be removed and the code will act exactly the same (but be faster in some scenarios). Commented Sep 9, 2020 at 1:15
  • As @mjwills commented "fetching from db" pretty much guarantees that calling .Count separately would cause double evaluation of the DB query... with corresponding correctness and performance cost. (in most cases loosing some performance could be ok, but code that can't be correct is rarely useful) Commented Sep 9, 2020 at 1:18
  • 1
    you mean remove || source.Count == 0 ? Yes. Commented Sep 9, 2020 at 1:27
  • 1
    Correct, it can't be done easily. Commented Sep 9, 2020 at 1:40

1 Answer 1

2

I strongly suspect that:

public static decimal? NullableSum(IQueryable<decimal?> source)
{
    return source.Sum();
}

will give you the outcome that you want - since IQueryable's Sum uses the database's Sum - and SQL Server's Sum does what you want "out of the box". This will also have the benefit of not passing all of the data over the wire (which your current code does).

Clearly writing this method is unnecessary - you can just call the built in Sum.

Given this functionality is built in, there is thus no need to "genericize" it - since it is already there, ready to use.

Sign up to request clarification or add additional context in comments.

5 Comments

yes I was using the original Sum method, but had to implement this as stated in the Summary comments that I added to the original post.
The built in Sum (the IQueryable one - not the IEnumerable one) does all of those things already @Riz. It will add up any numbers if they are there. If there is no data it will return NULL. If all of the data is NULL it will return NULL. Well, that is what my SQL testing is showing now. Which of the scenarios are not working for you?
sorry I had implemented this a few months back so didn't remember the details, but it turns out that I am only using this after the data has been fetched into a list and further calculations need to be done on the list. I remember it not giving the results that we wanted for those specific cases.
Gotcha - in a list then you will see the behaviour yes - since that is using the IEnumerable one. Hence why you should use the IQueryable one @Riz.
thanks for your help. I'll mark your answer as correct since it is techincally answering what I asked for and also helped me quite a bit and should help others.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.