简体   繁体   English

如何计算IEnumerable的项目?

[英]How to count the items of an IEnumerable?

Given an instance IEnumerable o how can I get the item Count ? 给定一个实例IEnumerable o我如何获得Count项? (without enumerating through all the items ) (不列举 所有项目

For example, if the instance is of ICollection , ICollection<T> and IReadOnlyCollection<T> , each of these interfaces have their own Count method. 例如,如果实例是ICollectionICollection<T>IReadOnlyCollection<T> ,则这些接口中的每个接口都有其自己的Count方法。

Is getting the Count property by reflection the only way? 通过反射获取Count属性是唯一的方法吗?

Instead, can I check and cast o to ICollection<T> for example, so I can then call Count ? 相反,例如,我可以检查并将o ICollection<T>ICollection<T> ,以便随后调用Count吗?

Ienumerable doesn't promise a count . 无数不能保证一切。 What if it was a random sequence or a real time data feed from a sensor? 如果是来自传感器的随机序列或实时数据馈送该怎么办? It is entirely possible for the collection to be infinitely sized. 集合的大小完全有可能是无限的。 The only way to count them is to start at zero and increment for each element that the enumerator provides. 计数它们的唯一方法是从零开始,然后为枚举器提供的每个元素递增。 Which is exactly what LINQ does, so don't reinvent the wheel. LINQ正是这样做的,所以不要重新发明轮子。 LINQ is smart enough to use .Count properties of collections that support this. LINQ非常聪明,可以使用支持此功能的集合的.Count属性。

The only way to really cover all your possible types for a collection is to use the generic interface and call the Count - method . 真正涵盖集合的所有可能类型的唯一方法是使用通用接口并调用Count 方法 This also covers other types such as streams or just iterators. 这也涵盖其他类型,例如流或仅迭代器。 Furthermore it will use the Count - property as of Count property vs Count() method? 此外,它会使用Count - 财产Count属性VS伯爵()方法? to avoid unneccessary overhead. 避免不必要的开销。

If you however have a non-generic collection you´d have to use reflection to use the correct property. 但是,如果您有非通用集合,则必须使用反射来使用正确的属性。 However this is cumbersome and may fail if your collection doesn´t even have the property (eg an endless stream or just an iterator). 但是,这很麻烦,如果您的集合甚至没有该属性(例如,无休止的流或只是一个迭代器),则可能会失败。 On the other hand IEnumerable<T>.Count() will handle those types with the optimization mentioned above. 另一方面, IEnumerable<T>.Count()将通过上述优化处理这些类型。 Only if neccessary it will iterate the entire collection. 仅在必要时才会迭代整个集合。

It depends how badly you want to avoid enumerating the items if the count is not available otherwise. 如果计数不可用,这取决于您希望避免枚举项目的严重程度。

If you can enumerate the items, you can use the LINQ method Enumerable.Count . 如果可以枚举项目,则可以使用LINQ方法Enumerable.Count It will look for a quick way to get the item count by casting into one of the interfaces. 它将寻找一种快速的方法,通过将其转换为一个界面来获取项目计数。 If it can't, it will enumerate. 如果不能,它将枚举。

If you want to avoid enumeration at any cost, you will have to perform a type cast. 如果要不惜一切代价避免枚举,则必须执行类型转换。 In a real life scenario you often will not have to consider all the interfaces you have named, since you usually use one of them ( IReadOnlyCollection is rare and ICollection only used in legacy code). 在现实生活中,您通常不必考虑所有已命名的接口,因为您通常使用其中之一( IReadOnlyCollection很少见,而ICollection仅在旧版代码中使用)。 If you have to consider all of the interfaces, try them all in a separate method, which can be an extension: 如果必须考虑所有接口,请在单独的方法中尝试它们,可以将其扩展:

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

Access the extension method with: 使用以下方法访问扩展方法:

int? count = myEnumerable.TryCount();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM