在.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();
}
答案 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”:)