109

I have a HQL query that can generate either an IList of results, or an IEnumerable of results.

However, I want it to return an array of the Entity that I'm selecting, what would be the best way of accomplishing that? I can either enumerate through it and build the array, or use CopyTo() a defined array.

Is there any better way? I went with the CopyTo-approach.

jishi
  • 24,126
  • 6
  • 49
  • 75

4 Answers4

182

Which version of .NET are you using? If it's .NET 3.5, I'd just call ToArray() and be done with it.

If you only have a non-generic IEnumerable, do something like this:

IEnumerable query = ...;
MyEntityType[] array = query.Cast<MyEntityType>().ToArray();

If you don't know the type within that method but the method's callers do know it, make the method generic and try this:

public static void T[] PerformQuery<T>()
{
    IEnumerable query = ...;
    T[] array = query.Cast<T>().ToArray();
    return array;
}
gonzobrains
  • 7,856
  • 14
  • 81
  • 132
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 1
    It's 3.5 but the IQuery doesn't have a ToArray, nor does IEnumerable or IList either as far as I can tell? – jishi Nov 06 '08 at 13:38
  • Thanks man, that was useful. Would you say that there is any difference in calling Cast<>() from the IList vs the IEnumerable? – jishi Nov 06 '08 at 13:45
  • 2
    No - there's just the one extension method. (It's not within the interface itself.) – Jon Skeet Nov 06 '08 at 13:47
  • What if I don't know what MyEntityType will be when I create that array? – topwik Sep 10 '09 at 21:37
  • Then how are you going to use it afterwards anyway? If only your *caller* knows, then make it a generic type parameter in the method containing this code. – Jon Skeet Sep 10 '09 at 21:57
  • not sure i completely follow you. you mean something like var array = list.Cast().ToArray(); ? – topwik Sep 10 '09 at 22:01
  • I want to convert a non-generic IEnumerable to an Array, how should I do it? I prefer not using the cast, as there is no point in it. – Shimmy Weitzhandler Jul 29 '10 at 14:12
  • 4
    @Shimmy: Yes there is... aside from anything else, it's telling the compiler what kind of array to expect! If you only want an `object[]` just use `Cast`. The nongeneric `IEnumerable` doesn't have a `ToArray` extension method, so you can't just call `foo.ToArray` or anything like that. – Jon Skeet Jul 29 '10 at 14:19
  • I am basically looking for the non-generic ToArray() method, it's already on my extension library using Cast, thanks Jon! – Shimmy Weitzhandler Jul 29 '10 at 16:16
  • 26
    The `ToArray` extension method is in the `System.Linq` namespace, thought that might be good to know :). – Tomas Jansson Nov 10 '10 at 08:52
  • @TomasJansson Thank you. I cleared unused usings and that's how I was missing that method. – Paul-Sebastian Manole Jan 26 '13 at 19:24
  • BTW, if I return IEnumerable for various types (reflection call) - may i use `(MyEntityType[])query` instead of `query.Cast().ToArray()`? – Alexander Sep 14 '15 at 13:03
  • 1
    @Alexander: Not unless the value being returned really *is* an appropriate array. – Jon Skeet Sep 14 '15 at 13:05
50

Put the following in your .cs file:

using System.Linq;

You will then be able to use the following extension method from System.Linq.Enumerable:

public static TSource[] ToArray<TSource>(this System.Collections.Generic.IEnumerable<TSource> source)

I.e.

IEnumerable<object> query = ...;
object[] bob = query.ToArray();
Michael Joyce
  • 601
  • 5
  • 3
6

I feel like reinventing the wheel...

public static T[] ConvertToArray<T>(this IEnumerable<T> enumerable)
{
    if (enumerable == null)
        throw new ArgumentNullException("enumerable");

    return enumerable as T[] ?? enumerable.ToArray();
}
Philippe Matray
  • 1,511
  • 1
  • 13
  • 22
  • can you explain your answer and also what you mean by you feel like you're reinventing the wheel? – ChrisCamp Jun 06 '13 at 20:03
  • heh - I actually kind of like this: in the off chance the enumerable is actually an array, you're skipping the new allocation/copy to steps in the `ToArray()` call (via the internal `Buffer` class)...although if anyone expected the "standard" copy behavior, they'd be quite surprised. – JerKimball Jun 06 '13 at 20:39
  • @Chris : Because I was inspired by the signature of ToArray () method in System.Linq. http://msdn.microsoft.com/en-us/library/bb298736.aspx – Philippe Matray Jun 08 '13 at 09:15
  • For added ridiculousness the implementation of this method should call `IEnumerable.ToArray()` – The Muffin Man Dec 23 '16 at 19:10
6

In case you don't have Linq, I solved it the following way:

    private T[] GetArray<T>(IList<T> iList) where T: new()
    {
        var result = new T[iList.Count];

        iList.CopyTo(result, 0);

        return result;
    }

Hope it helps

Lug
  • 420
  • 5
  • 15