计算IEnumerable(非泛型)的计数



谁能帮我一个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/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;
}

不同类型的IEnumerable有不同的确定计数的最佳方法;不幸的是,没有通用的方法可以知道哪种方法最适合任何给定的IEnumerable,甚至也没有任何标准的方法可以让IEnumerable指出以下哪种技术是最好的:

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

我认为选择的类型来表示你的元素序列应该是ICollection而不是IEnumerable,首先。

ICollectionICollection<T>都提供了Count属性,并且每个iccollection都实现了ienumerable

相关内容

  • 没有找到相关文章