Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why generic ICollection<T> does not inherit some non-generic interface with Count property?

In .NET generic interface ICollection<T> has Count property itself. But it does not inherit any non-generic interface with a Count property.

So, now if you want determine count of non-generic IEnumerable, you have to check whether it is implementing ICollection and if not, you have to use reflection to lookup whether it does implement generic ICollection<X>, since you do not know the generic argument X.

If ICollection<T> cannot inherit from directly from ICollection, why there is not another non-generic interface with Count property only?

Is it just bad design choice?

UPDATE: To make the question more clear, I demonstrate the issue on my current implementation:

    static int? FastCountOrZero(this IEnumerable items)
    {
        if (items == null)
            return 0;
        var collection = items as ICollection;
        if (collection != null)
            return collection.Count;
        var source = items as IQueryable;
        if (source != null)
            return QueryableEx.Count(source);
        // TODO process generic ICollection<> - I think it is not possible without using reflection
        return items.Cast<object>().Count();
    }
like image 384
TN. Avatar asked Feb 26 '14 12:02

TN.


1 Answers

Is it just bad design choice?

Probably the answer is yes.

And to solve this issue in .NET 4.5 MS introduced IReadOnlyCollection<out T> interface, which is covariant for reference types.

So you can rewrite your code like following

static int? FastCountOrZero(this IEnumerable items)
{
    if (items == null)
        return 0;
    var collection = items as ICollection;
    if (collection != null)
        return collection.Count;
    var roCollection = items as IReadOnlyCollection<object>; // only for reference types
    if (roCollection != null)
        return roCollection.Count;
    var source = items as IQueryable;
    if (source != null)
        return QueryableEx.Count(source);

    return items.Cast<object>().Count();
}

And as last resort you can cast items to dynamic object and invoke Count property dynamicly.

if (items.GetType().GetInterface("System.Collections.Generic.ICollection`1") != null)
{
    dynamic dynamic = items;
    return dynamic.Count;
}
like image 63
hazzik Avatar answered Sep 18 '22 16:09

hazzik