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

Ever tried to use IEnumerable<T>.Sum on an array of unsigned long inte­gers? Well, you can’t, because the Sum method has not been imple­ment­ed for ulong or ulong?, so to fill in the gap here’s the exten­sion meth­ods you need using more or less the same code as the exist­ing Sum meth­ods:

[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 cus­tom Post­Sharp attrib­ut­es here to do the para­me­ter val­i­da­tion, but you can just as eas­i­ly sub­sti­tute them with if null then throw excep­tion code blocks.

UPDATE 10/11/2010:

Using the dynam­ic type in .Net 4 you can make these exten­sion meth­ods even more use­ful by mak­ing them usable with oth­er val­ue types too.

Tra­di­tion­al­ly for exten­sion meth­ods like Sum, you’d have to pro­vide an over­load for each numer­ic val­ue type (int, uint, long, etc.) because these numer­ic val­ue types don’t have a com­mon super type which defines the numer­ic oper­a­tors +, -, /, *, etc.

For­tu­nate­ly, you can now negate this com­pile time lim­i­ta­tion by mak­ing it a run­time deci­sion using the new dynam­ic capa­bil­i­ties:

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 obvi­ous fal­la­cy with this approach is that you can now pass cus­tom struc­tures with no defined + oper­a­tor into these exten­sion meth­ods and no com­pile errors will be thrown, but a Run­time­BinderEx­cep­tion will be thrown by the DLR at run­time with a mes­sage like this:

Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: Oper­a­tor ‘+’ can­not be applied to operands of type ‘xxx’ and ‘xxx’