为什么泛型 ICollection<T> 不继承一些具有 Count 属性的非泛型接口?



在.NET泛型接口中,ICollection<T>本身具有Count属性。但它不会继承任何具有 Count 属性的非泛型接口。

所以,现在如果你想确定非泛型IEnumerable的计数,你必须检查它是否在实现ICollection,如果没有,你必须使用反射来查找它是否实现了泛型ICollection<X>,因为你不知道泛型参数X

如果ICollection<T>不能直接从ICollection继承,为什么没有另一个只有Count属性的非泛型接口?

只是糟糕的设计选择吗?

更新:为了使问题更清晰,我在当前的实现中演示了该问题:

    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();
    }

只是糟糕的设计选择吗?

答案可能是肯定的

为了解决这个问题,在.NET 4.5 MS中引入了IReadOnlyCollection<out T>接口,该接口对于引用类型是协变的。

因此,您可以像下面这样重写代码

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();
}

作为最后的手段,您可以将items强制转换为动态对象并动态调用Count属性。

if (items.GetType().GetInterface("System.Collections.Generic.ICollection`1") != null)
{
    dynamic dynamic = items;
    return dynamic.Count;
}

我能建议的最好的就是这个。注意(如注释中所述,Ienumerable 可以是无限的)

public static int CountIEnumerable (IEnumerable t)
{
    var iterator = t.GetEnumerator();
    var max = int.MaxValue;
    int count = 0;
    while (iterator.MoveNext() && (count < max))
    {
        count++;
    }
    //OPTIONAL
    //if (count >= max)
    //{
       //   throw new Exception("Collection is too big");
    //}
    return count;
    }

编辑:您可以将"int"替换为 Int64 :)

最新更新