计算IEnumerable的计数(非通用)

时间:2011-04-09 09:34:56

标签: c# .net linq extension-methods ienumerable

任何人都可以帮助我使用Count IEnumerable扩展方法(非通用接口)。

我知道LINQ不支持它但是如何手动编写它?

4 个答案:

答案 0 :(得分:47)

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

答案 1 :(得分:42)

最简单的形式是:

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 / finallyusing语句。

为了在其他情况下也很容易,你可以制作自己的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;
}

答案 2 :(得分:4)

不同类型的IEnumerable有不同的最佳方法来确定计数;遗憾的是,没有通用的方法可以知道哪种方法最适合任何给定的IEnumerable,甚至没有任何标准方法可以通过IEmumerable来指示以下哪种技术最佳:

  1. 只需直接询问对象即可。支持IEnumerable的某些类型的对象(如Array,List和Collection)具有可以直接报告其中元素数量的属性。
  2. 枚举所有项目,丢弃它们,并计算枚举的项目数。
  3. 将所有项目枚举到列表中,然后在需要再次使用枚举时使用该列表。

以上各项在不同情况下都是最佳的。

答案 3 :(得分:3)

我认为选择用于表示元素序列的类型应该首先是 ICollection而不是IEnumerable

ICollectionICollection<T>都提供了Count属性 - 而且 - 每个ICollection也实现了IEnumearable。