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.


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

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();

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

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

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.