开发者

Calculating Count for IEnumerable (Non Generic)

Can any开发者_高级运维one 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?


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


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


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.


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜