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();
}
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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With