给定一个实例IEnumerable o
,我如何获得商品 Count ? (没有枚举到所有项目)
例如,如果实例是ICollection
,ICollection<T>
和IReadOnlyCollection<T>
的实例,则这些接口中的每个接口都有自己的Count
方法。
通过 reflection 来获得Count
属性是唯一的方法吗?
例如,我可以检查并将o
强制转换为ICollection<T>
,以便随后致电Count
吗?
答案 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();