Calculating Count for IEnumerable (Non Generic)

我的未来我决定 提交于 2019-12-17 15:47:24

问题


Can anyone help me with a Count extension method for IEnumerable (non generic interface).

I know it is not supported in LINQ but how to write it manually?


回答1:


The simplest form would be:

public static int Count(this IEnumerable source)
{
    int c = 0;
    using (var e = source.GetEnumerator())
    {
        while (e.MoveNext())
            c++;
    }
    return c;
}

You can then improve on this by querying for 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;
}

Update

As Gerard points out in the comments, non-generic IEnumerable does not inherit IDisposable so the normal using statement won't work. It is probably still important to attempt to dispose of such enumerators if possible - an iterator method implements IEnumerable and so may be passed indirectly to this Count method. Internally, that iterator method will be depending on a call to Dispose to trigger its own try/finally and using statements.

To make this easy in other circumstances too, you can make your own version of the using statement that is less fussy at compile time:

public static void DynamicUsing(object resource, Action action)
{
    try
    {
        action();
    }
    finally
    {
        IDisposable d = resource as IDisposable;
        if (d != null)
            d.Dispose();
    }
}

And the updated Count method would then be:

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:


yourEnumerable.Cast<object>().Count()

To the comment about performance:

I think this is a good example of premature optimization but here you go:

static class EnumerableExtensions
{
    public static int Count(this IEnumerable source)
    {
        int res = 0;

        foreach (var item in source)
            res++;

        return res;
    }
}



回答3:


Different types of IEnumerable have different optimal methods for determining count; unfortunately, there's no general-purpose means of knowing which method will be best for any given IEnumerable, nor is there even any standard means by which an IEmumerable can indicate which of the following techniques is best:

  1. Simply ask the object directly. Some types of objects that support IEnumerable, such as Array, List and Collection, have properties which can directly report the number of elements in them.
  2. Enumerate all items, discarding them, and count the number of items enumerated.
  3. Enumerate all items into a list, and then use the list if it's necessary to use the enumeration again.

Each of the above will be optimal in different cases.




回答4:


I think the type chosen to represent your sequence of elements should have been ICollection instead of IEnumerable, in the first place.

Both ICollection and ICollection<T> provide a Count property - plus - every ICollection implements IEnumearable as well.



来源:https://stackoverflow.com/questions/5604168/calculating-count-for-ienumerable-non-generic

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!