如何计算IEnumerable的项?

时间:2018-09-24 09:30:32

标签: c#

给定一个实例IEnumerable o,我如何获得商品 Count ? (没有枚举所有项目

例如,如果实例是ICollectionICollection<T>IReadOnlyCollection<T>的实例,则这些接口中的每个接口都有自己的Count方法。

通过 reflection 来获得Count属性是唯一的方法吗?

例如,我可以检查并将o强制转换为ICollection<T>,以便随后致电Count吗?

3 个答案:

答案 0 :(得分:4)

Inumerable不保证计数。如果是来自传感器的随机序列或实时数据馈送该怎么办?集合的大小完全有可能是无限的。计数它们的唯一方法是从零开始,然后为枚举器提供的每个元素递增。 LINQ正是这样做的,所以不要重新发明轮子。 LINQ非常聪明,可以使用支持此功能的集合的.Count属性。

答案 1 :(得分:1)

真正涵盖集合的所有可能类型的唯一方法是使用通用接口并调用Count-方法。这也涵盖其他类型,例如流或仅迭代器。此外,它将自Count property vs Count() method?起使用IEnumerable<T>.Count()-属性,以避免不必要的开销。

但是,如果您有一个非通用集合,则必须使用反射来使用正确的属性。但是,这很麻烦,如果您的集合甚至没有拥有属性(例如,无尽的流或只是一个迭代器),则可能会失败。另一方面,{{1}}将使用上述优化来处理这些类型。仅在必要时才会迭代整个集合。

答案 2 :(得分:1)

这取决于您希望在没有计数的情况下避免枚举项目的严重程度。

如果可以枚举项目,则可以使用LINQ方法Enumerable.Count。它将寻找一种快速的方法,通过将其转换为一个界面来获取项目计数。如果不能,它将枚举。

如果您想不惜一切代价避免枚举,则必须执行类型转换。在现实生活中,您通常不必考虑所有已命名的接口,因为您通常使用其中一个接口(IReadOnlyCollection很罕见,ICollection仅在旧版代码中使用)。如果您必须考虑所有接口,请在单独的方法中尝试它们,可以将其扩展:

static class CountExtensions {
    public static int? TryCount<T>(this IEnumerable<T> items) {
        switch (items) {
            case ICollection<T> genCollection:
                return genCollection.Count;
            case ICollection legacyCollection:
                return legacyCollection.Count;
            case IReadOnlyCollection<T> roCollection:
                return roCollection.Count;
            default:
                return null;
        }
    }
}

通过以下方式访问扩展方法:

int? count = myEnumerable.TryCount();