Extension methods to sum IEnumerable(ulong) and IEnumerable(ulong?)

Yan Cui

I help clients go faster for less using serverless technologies.

Ever tried to use IEnumerable<T>.Sum on an array of unsigned long integers? Well, you can’t, because the Sum method has not been implemented for ulong or ulong?, so to fill in the gap here’s the extension methods you need using more or less the same code as the existing Sum methods:

[CheckParameters]
public static ulong Sum([NotNull] this IEnumerable<ulong> source)
{
    var sum = 0UL;
    foreach (var number in source)
    {
        sum += number;
    }
    return sum;
}

[CheckParameters]
public static ulong? Sum([NotNull] this IEnumerable<ulong?> source)
{
    var sum = 0UL;
    foreach (var nullable in source)
    {
        if (nullable.HasValue)
        {
            sum += nullable.GetValueOrDefault();
        }
    }
    return sum;
}

[CheckParameters]
public static ulong Sum<T>([NotNull] this IEnumerable<T> source, Func<T, ulong> selector)
{
    return source.Select(selector).Sum();
}

[CheckParameters]
public static ulong? Sum<T>([NotNull] this IEnumerable<T> source, Func<T, ulong?> selector)
{
    return source.Select(selector).Sum();
}

I used some custom PostSharp attributes here to do the parameter validation, but you can just as easily substitute them with if null then throw exception code blocks.

UPDATE 10/11/2010:

Using the dynamic type in .Net 4 you can make these extension methods even more useful by making them usable with other value types too.

Traditionally for extension methods like Sum, you’d have to provide an overload for each numeric value type (int, uint, long, etc.) because these numeric value types don’t have a common super type which defines the numeric operators +, -, /, *, etc.

Fortunately, you can now negate this compile time limitation by making it a runtime decision using the new dynamic capabilities:

public static T Sum<T>(this IEnumerable<T> source) where T : struct
{
    return source.Aggregate(default(T), (current, number) => (dynamic) current + number);
}
public static T? Sum<T>(this IEnumerable<T?> source) where T : struct
{
    return source.Where(nullable => nullable.HasValue)
                 .Aggregate(
                     default(T),
                     (current, nullable) => (dynamic) current + nullable.GetValueOrDefault());
}
public static V Sum<T, V>(this IEnumerable<T> source, Func<T, V> selector) where V : struct
{
    return source.Select(selector).Sum();
}
public static V? Sum<T, V>(this IEnumerable<T> source, Func<T, V?> selector) where V : struct
{
    return source.Select(selector).Sum();
}

The obvious fallacy with this approach is that you can now pass custom structures with no defined + operator into these extension methods and no compile errors will be thrown, but a RuntimeBinderException will be thrown by the DLR at runtime with a message like this:

Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: Operator ‘+’ cannot be applied to operands of type ‘xxx’ and ‘xxx’


Whenever you’re ready, here are 3 ways I can help you:

  1. Production-Ready Serverless: Join 20+ AWS Heroes & Community Builders and 1000+ other students in levelling up your serverless game.
  2. Consulting: If you want to improve feature velocity, reduce costs, and make your systems more scalable, secure, and resilient, then let’s work together and make it happen.
  3. Join my FREE Community on Skool, where you can ask for help, share your success stories and hang out with me and other like-minded people without all the negativity from social media.

 

Leave a Comment

Your email address will not be published. Required fields are marked *