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

时间:2014-02-26 12:43:23

标签: c# .net generics collections

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

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

如果ICollection<T> cannot inherit from directly from 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();
    }

2 个答案:

答案 0 :(得分:3)

  

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

答案可能是

为了解决这个问题,在.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;
}

答案 1 :(得分:-1)

我能提出的最好的就是这个。注意(如评论中所述,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;
    }

编辑:您可以用Int64替换“int”:)