2013-01-05 9 views
5

Sto leggendo C# AsEnumerable:..Perché applicare il metodo AsEnumerable() a una matrice?

"L'interfaccia IEnumerable è un'interfaccia generica Questo significa che definisce un modello che i tipi possono implementare per il ciclo Il metodo AsEnumerable, un metodo generico, ti permette di lanciare un specifico tipo nell'equivalente IEnumerable"

Più avanti, un esempio di codice:

using System; 
using System.Linq; 

class Program 
{ 
    static void Main() 
    { 
     // Create an array type. 
     int[] array = new int[2]; 
     array[0] = 5; 
     array[1] = 6; 
     // Call AsEnumerable method. 
     var query = array.AsEnumerable(); 
     foreach (var element in query) 
     { 
      Console.WriteLine(element); 
     } 
    } 
} 

Sembra che debba convertire un array in un oggetto tipo IEnumerable per utilizzare il looping (foreach?).

ma applicando foreach direttamente ad una serie rendimenti esattamente gli stessi risultati:

using System; 
//using System.Linq; 

class Program 
{ 
    static void Main() 
    { 
     // Create an array type. 
     int[] array = new int[2]; 
     array[0] = 5; 
     array[1] = 6; 
     // Call AsEnumerable method. 
     //var query = array.AsEnumerable(); 
     foreach (var element in array) 
     { 
      Console.WriteLine(element); 
     } 
    } 
} 

Così, l'intera pagina web con una spiegazione di AsEnumerable() metodo è vuoto per me.
Cosa mi sono perso?

+3

+1 l'esempio è completamente stupido, e l'autore della pagina web non ha idea di cosa sia utilizzato "AsEnumerable". –

+1

Grazie a tutti i rispondenti per l'aiuto e in particolare al commentatore [@ Konrad Rudolph] (http://stackoverflow.com/users/1968/konrad-rudolph) per avermi tenuto lontano dai problemi per essere confuso con una persona interessata alla sintassi di un metodo di utilizzo.La chiave in questione era ciò che io (ma non l'articolo citato, che ho capito prima di chiedere) perso. Ho letto tutte le risposte poche volte ma preferisco davvero le illustrazioni del codice allegate per la lettura invece di leggere teorie molto sagge e corrette. Sembra che la risposta corretta abbia sofferto un downvote per il gusto di prendermi dei problemi per educarmi. –

risposta

4

L'esempio è negativo e dovrebbe essere negativo. Qui è una migliore, se ad esempio un po 'artificiosa:

Se ho un metodo di estensione definita sulla, diciamo, il tipo di matrice, come questo:

public static class ArrayExtension { 

    public static bool Any<T>(this T[] source, Func<T,bool> predicate) 
    { 
     Console.WriteLine("Undesirable side behaviour"); 
     SomeResourceIntensiveOperation(); 

     Console.WriteLine("Inefficient implementation"); 
     return source.Where(predicate).Count() != 0; 
    } 

} 

e lo faccio

int[] nums = new []{1,2,3,4,5}; 
nums.Any(n=> n % 2 == 0); 

Se eseguirà ed eseguirà la mia implementazione, anche se non ne ho bisogno. Facendo

nums.AsEnumerable().Any(n => n % 2 == 0); 

chiamerà l'implementazione di default.

Il vero vantaggio è quando si utilizza IQueryable implementazioni (ad esempio LINQ to SQL), perché, ad esempio, il Where for IEnumerable è definito come

public static IEnumerable<TSource> Where<TSource>(
this IEnumerable<TSource> source, 
Func<TSource, bool> predicate) 

ma il IQueryable.Where viene definito con

public static IQueryable<TSource> Where<TSource>(
this IQueryable<TSource> source, 
Expression<Func<TSource, bool>> predicate) 

Quando il comportamento IQueryable non è disponibile, è possibile chiamare AsEnumerable() per forzare il comportamento IEnumerable.

+0

Scusa, questo è l'esempio più ridicolo che abbia mai visto. Regola per esempio: KISS. Il più semplice possibile. PER FARE l'UNO punto che fai. Ci sono così tante spiegazioni non così carine che potrebbero anche non essere già uscite e riferimenti incrociati - spero solo che tu non scriva mai un tutorial di programmazione. – TomTom

+5

@TomTom Devi essere completamente fuori dal tuo dondolo. Questo esempio è l'illustrazione * perfetta * di ciò che fa AsEnumerable. In particolare, è un esempio ** minimo **. Non contiene nient'altro che gli ingredienti minimi per illustrarne l'utilizzo. Ti suggerisco di dormire una notte su questo, poi torna a guardarlo di nuovo. –

+0

@TomTom Mi è sempre piaciuta una variazione su KISS: "Mantieni il più semplice possibile, ma non più semplice." :) E non penso davvero che questo metodo di estensione venga spiegato quando spieghi un metodo di estensione che sta complicando le cose. – SWeko

1

Non ha senso nel TUO esempio logicamente (cioè dalla matrice). Immagino che il primo codice sia stato scritto da un principiante, o - più in basso - un esempio.

Ha senso nel senso di LINQ come "AsEnumerable" attiva la valutazione della query e in base all'ORM Ciò può significare liberare una connessione al database per un riutilizzo all'interno del ciclo.

che dicono:

Tu leggi troppo in esempi. In un esempio, il codice non deve essere "buono" ma mostrare un punto. In questo caso può avere senso DIMOSTRARE l'uso di AsEnumerable - e una matrice è l'oggetto enumerabile più veloce da inizializzare (in termini di righe di codice), per mantenere l'esempio breve. Gli esempi indicano cose specifiche, non sono "codice buono" per niente.

+1

Non sono d'accordo. Come hai detto tu, "in un esempio, il codice è lì ... per mostrare un punto". L'esempio nella domanda non riesce assolutamente a farlo, poiché non vi è * nessun punto * nell'applicare 'AsEnumerable' in un array. Un buon esempio mostrerebbe la differenza tra utilizzarlo e non usarlo in una query LINQ a SQL. Hai letto l'OP del sito web collegato? Il suo autore è completamente all'oscuro. –

+0

Dimostra l'utilizzo dal punto di vista della sintassi. – TomTom

+1

Quanto è pertinente o utile? Nessuno ha bisogno di sentirsi dire come chiamare un metodo comune. Avrebbero potuto ugualmente dimostrare lo stesso chiamando 'foo.Bar()' con nomi inventati, senza bisogno di menzionare 'System.Array' e' AsEnumerable'. L'esempio non mostra più di questo. –

2

Da MSDN

Procedimento AsEnumerable<TSource> (IEnumerable<TSource>) non ha effetto se non per cambiare la fase di compilazione di origine da un tipo che implementa IEnumerable<T> a IEnumerable<T> stessa.

AsEnumerable<TSource> (IEnumerable<TSource>) può essere utilizzato per scegliere tra le implementazioni di query quando una sequenza implementa IEnumerable<T> ma ha anche un diverso insieme di metodi di query pubblici disponibili. Ad esempio, data una tabella di classe generica che implementa IEnumerable<T> e ha i propri metodi come Where, Select e SelectMany, una chiamata a Where invocherebbe il metodo pubblico di Tabella Where. Un tipo di tabella che rappresenta una tabella di database può avere un metodo Where che prende l'argomento predicato come un albero di espressioni e converte l'albero in SQL per l'esecuzione remota. Se l'esecuzione remota non è desiderata, ad esempio perché il predicato richiama un metodo locale, è possibile utilizzare il metodo AsEnumerable<TSource> per nascondere i metodi personalizzati e rendere invece disponibili gli operatori di query standard.

0

Questo è solo un altro esempio. Supponiamo che io sono questo metodo:

static void MyMeth(int[] numbers) 
{ 
    var query = numbers.Reverse(); // works fine, calls Linq extension 

    // ... use query ... 
} 

Poi decido di cambiare numbers in un List<int> invece, e provare:

static void MyMeth(List<int> numbers) 
{ 
    var query = numbers.Reverse(); // will not compile! 

    // ... use query ... 
} 

Il problema qui è che la classe List<> ha un altro metodo che è anche chiamato Reverse. Questo metodo restituisce void (perché modifica l'originale List<> sul posto). Non lo voglio Una soluzione potrebbe essere quella di upcast numbers esplicitamente:

static void MyMeth(List<int> numbers) 
{ 
    var query = ((IEnumerable<int>)numbers).Reverse(); // fine; Linq 

    // ... use query ... 
} 

Ma un'altra soluzione sarebbe AsEnumerable<>, così:

static void MyMeth(List<int> numbers) 
{ 
    var query = numbers.AsEnumerable().Reverse(); // fine too; Linq 

    // ... use query ... 
} 

Conclusione: Lo scopo di AsEnumerable metodo è quello di "dimenticare" metodi sul specializzato digitare che capita di "nascondere" i metodi di estensione sul tipo generale IEnumerable<>. Questo può essere incredibilmente importante nel caso in cui il tipo "specializzato" è/eredita IQueryable<> dove ci sono (estensione) metodi Where, Select e così via che fanno qualcosa di diverso (vale a dire ingerire il lambda come albero di espressione, analizzarlo, e " traduci "in SQL o qualcosa del genere) rispetto a Where, Select ecc. su IEnumerable<>.

Problemi correlati