views:

1302

answers:

3

What is the best way to convert from a generic IEnumerable object to an array of the same type? The current solution I have looks like the following:

IEnumerable<string> foo = getFoo();
string[] bar = new List<string>(foo).ToArray();

The transfer through a List<T> seems unneccesary, but I haven't been able to find a better way to do it.

Note: I'm working in C# 2.0 here.

A: 

If there's no way to determine the length of the array, then that's the best way.

There's nothing in IEnumerable that will let you determine the length, but perhaps your code has a way of finding out another way. If so, use that to construct an array.

Ray Hidayat
+9  A: 

Generally speaking, using a List<T> which will be initialized with the IEnumerable<T> and then calling ToArray is probably the easiest way to do this.

The constructor for List will check the IEnumerable<T> to see if it implements ICollection<T> to get the count of items to properly initialize the capacity of the list. If not, it will expand as normal.

Of course, you might end up creating a number of List<T> instances just for the purpose of transforming IEnumerable<T> to T[]. To that end, you can write your own method, but you would really just be duplicating the code that exists in List<T> already.

casperOne
True. If you have the count from another source, though, and not from the IEnumerable<>'s other interfaces (like ICollection), you should use your count to create an array yourself. Any other way, passing through a list would probably be best.
configurator
+4  A: 

Doing a little .NET Reflector it looks like the Linq ToArray extension method basically does the same thing as passing the IEnumerable through a List<>. The Buffer class is an internal, but the behavior seems very similar to List<>.

public static TSource[] ToArray<TSource>(this IEnumerable<TSource> source)
{
    if (source == null)
    {
        throw Error.ArgumentNull("source");
    }
    Buffer<TSource> buffer = new Buffer<TSource>(source);
    return buffer.ToArray();
}
Rob McCready