有谁能为我提供一个 IEnumerable
的 Count
扩展方法(非泛型接口)?
我知道它在 LINQ 中不受支持,但该如何手动编写呢?
有谁能为我提供一个 IEnumerable
的 Count
扩展方法(非泛型接口)?
我知道它在 LINQ 中不受支持,但该如何手动编写呢?
yourEnumerable.Cast<object>().Count()
针对性能的评论:
我认为这是过早优化的一个好例子,但以下是代码:
static class EnumerableExtensions
{
public static int Count(this IEnumerable source)
{
int res = 0;
foreach (var item in source)
res++;
return res;
}
}
最简单的形式是:
public static int Count(this IEnumerable source)
{
int c = 0;
using (var e = source.GetEnumerator())
{
while (e.MoveNext())
c++;
}
return c;
}
你可以通过查询 ICollection
来进一步完善此操作:
public static int Count(this IEnumerable source)
{
var col = source as ICollection;
if (col != null)
return col.Count;
int c = 0;
using (var e = source.GetEnumerator())
{
while (e.MoveNext())
c++;
}
return c;
}
更新
正如Gerard在评论中指出的那样,非泛型的 IEnumerable
并不继承 IDisposable
,因此普通的 using
语句将无法工作。如果可能的话,尝试释放这些枚举器仍然很重要 - 迭代器方法实现了 IEnumerable
,因此可能会通过间接方式传递给此 Count
方法。在内部,该迭代器方法将依赖于对 Dispose
的调用来触发自己的 try
/finally
和 using
语句。
为了让其他情况下更容易实现,你可以创建自己版本的 using
语句,它在编译时要求较少:
public static void DynamicUsing(object resource, Action action)
{
try
{
action();
}
finally
{
IDisposable d = resource as IDisposable;
if (d != null)
d.Dispose();
}
}
更新后的Count
方法如下:
public static int Count(this IEnumerable source)
{
var col = source as ICollection;
if (col != null)
return col.Count;
int c = 0;
var e = source.GetEnumerator();
DynamicUsing(e, () =>
{
while (e.MoveNext())
c++;
});
return c;
}
using
对于 System.Collections.IEnumerable
报编译错误。我将代码更改为 Count<T>(this IEnumerable<T> source)
可以通过编译。 - Gerard我认为在第一次选择表示元素序列的类型时,应该选择ICollection而不是IEnumerable。
ICollection
和ICollection<T>
都提供一个Count属性,此外每个ICollection也实现了IEnumerable接口。
ICollection
的答案更好,就这样说吧... - Marc Gravell.Cast<object>().Count()
已经进行了检查(泛型和非泛型)。但是,是的,第二种解决方案可以通过检查来改进。 - Lasse Espeholt