Meilleur moyen de convertir IList ou IEnumerable en Array

99

J'ai une requête HQL qui peut générer soit une IList de résultats, soit un IEnumerable de résultats.

Cependant, je veux qu'il renvoie un tableau de l'entité que je sélectionne, quelle serait la meilleure façon d'y parvenir? Je peux soit énumérer et construire le tableau, soit utiliser CopyTo () un tableau défini.

Y a-t-il une meilleure façon? J'ai opté pour l'approche CopyTo.

jishi
la source
4
Quelqu'un a-t-il une solution sans Linq?
Bitterblue

Réponses:

167

Quelle version de .NET utilisez-vous? Si c'est .NET 3.5, j'appellerais juste ToArray()et en finirais avec lui.

Si vous n'avez qu'un IEnumerable non générique, faites quelque chose comme ceci:

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

Si vous ne connaissez pas le type dans cette méthode mais que les appelants de la méthode le savent, rendez la méthode générique et essayez ceci:

public static void T[] PerformQuery<T>()
{
    IEnumerable query = ...;
    T[] array = query.Cast<T>().ToArray();
    return array;
}
Jon Skeet
la source
C'est 3,5 mais IQuery n'a pas de ToArray, ni IEnumerable ou IList non plus pour autant que je sache?
jishi
2
Non - il n'y a qu'une seule méthode d'extension. (Ce n'est pas dans l'interface elle-même.)
Jon Skeet
3
@Shimmy: Oui, il y en a ... à part toute autre chose, cela indique au compilateur à quel type de tableau s'attendre! Si vous voulez seulement une object[]utilisation juste Cast<object>. Le non générique IEnumerablen'a pas de ToArrayméthode d'extension, vous ne pouvez donc pas simplement appeler foo.ToArray<object>ou quelque chose comme ça.
Jon Skeet
22
La ToArrayméthode d'extension est dans l' System.Linqespace de noms, je pense que cela pourrait être bon à savoir :).
Tomas Jansson
1
@Alexander: Pas à moins que la valeur renvoyée ne soit vraiment un tableau approprié.
Jon Skeet le
47

Mettez ce qui suit dans votre fichier .cs:

using System.Linq;

Vous pourrez alors utiliser la méthode d'extension suivante à partir de System.Linq.Enumerable:

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

C'est à dire

IEnumerable<object> query = ...;
object[] bob = query.ToArray();
Michael Joyce
la source
ahh ... le projet de test unitaire n'inclut pas le linq par défaut. Je vous remercie!
zsf222
6

J'ai envie de réinventer la roue ...

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

    return enumerable as T[] ?? enumerable.ToArray();
}
Philippe Matray
la source
pouvez-vous expliquer votre réponse et ce que vous entendez par vous sentir comme si vous réinventiez la roue?
ChrisCamp
heh - j'aime en fait un peu comme ceci: dans le cas où l'énumérable est en fait un tableau, vous sautez la nouvelle allocation / copie aux étapes de l' ToArray()appel (via la Bufferclasse interne ) ... bien que si quelqu'un attendait le "standard "copiez le comportement, ils seraient assez surpris.
JerKimball
@Chris: Parce que j'ai été inspiré par la signature de la méthode ToArray () dans System.Linq. msdn.microsoft.com/en-us/library/bb298736.aspx
Philippe Matray
Pour plus de ridicule, la mise en œuvre de cette méthode devrait appelerIEnumerable.ToArray()
The Muffin Man
2

Au cas où vous n'auriez pas Linq, je l'ai résolu de la manière suivante:

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

        iList.CopyTo(result, 0);

        return result;
    }

J'espère que ça aide

Patte
la source