Il modo migliore per convertire IList o IEnumerable in Array


99

Ho una query HQL che può generare un IList di risultati o un IEnumerable di risultati.

Tuttavia, desidero che restituisca un array dell'entità che sto selezionando, quale sarebbe il modo migliore per farlo? Posso enumerare attraverso di esso e costruire l'array, oppure usare CopyTo () un array definito.

C'è un modo migliore? Sono andato con l'approccio CopyTo.


4
Qualcuno ha una soluzione senza Linq?
Bitterblue

Risposte:


167

Quale versione di .NET stai usando? Se è .NET 3.5, chiamerei ToArray()e finirò con esso.

Se hai solo un IEnumerable non generico, fai qualcosa di simile:

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

Se non conosci il tipo all'interno di quel metodo ma i chiamanti del metodo lo conoscono, rendi il metodo generico e prova questo:

public static void T[] PerformQuery<T>()
{
    IEnumerable query = ...;
    T[] array = query.Cast<T>().ToArray();
    return array;
}

È 3.5 ma IQuery non ha un ToArray, né IEnumerable o IList per quanto ne so?
jishi

2
No, c'è solo un metodo di estensione. (Non è all'interno dell'interfaccia stessa.)
Jon Skeet

3
@ Shimmy: Sì, c'è ... a parte qualsiasi altra cosa, sta dicendo al compilatore che tipo di array aspettarsi! Se vuoi solo un object[]uso giusto Cast<object>. Il IEnumerablenon generico non ha un ToArraymetodo di estensione, quindi non puoi semplicemente chiamare foo.ToArray<object>o qualcosa del genere.
Jon Skeet

22
Il ToArraymetodo di estensione è nello System.Linqspazio dei nomi, pensato che potrebbe essere utile saperlo :).
Tomas Jansson

1
@Alexander: No, a meno che il valore restituito non sia davvero un array appropriato.
Jon Skeet

47

Inserisci quanto segue nel tuo file .cs:

using System.Linq;

Sarai quindi in grado di utilizzare il seguente metodo di estensione da System.Linq.Enumerable:

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

Cioè

IEnumerable<object> query = ...;
object[] bob = query.ToArray();

ahh ... il progetto di unit test non include linq di default. Grazie!
zsf222

6

Ho voglia di reinventare la ruota ...

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

    return enumerable as T[] ?? enumerable.ToArray();
}

puoi spiegare la tua risposta e anche cosa intendi con la sensazione di reinventare la ruota?
ChrisCamp

heh - In realtà mi piace questo: nella remota possibilità che l'enumerabile sia effettivamente un array, stai saltando la nuova allocazione / copia ai passaggi della ToArray()chiamata (tramite la Bufferclasse interna ) ... anche se qualcuno si aspettava lo standard " "copiare il comportamento, sarebbero piuttosto sorpresi.
JerKimball

@ Chris: perché sono stato ispirato dalla firma del metodo ToArray () in System.Linq. msdn.microsoft.com/en-us/library/bb298736.aspx
Philippe Matray

Per ulteriore ridicolo, l'implementazione di questo metodo dovrebbe chiamareIEnumerable.ToArray()
The Muffin Man

2

Nel caso non avessi Linq, l'ho risolto nel modo seguente:

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

        iList.CopyTo(result, 0);

        return result;
    }

Spero che sia d'aiuto

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.