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

TN.*_*TN. 9 .net c# generics collections

在.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();
    }
Run Code Online (Sandbox Code Playgroud)

haz*_*zik 4

这只是糟糕的设计选择吗?

或许答案是肯定的

为了解决这个问题,.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();
}
Run Code Online (Sandbox Code Playgroud)

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

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