2009-09-12 12 views

risposta

30

I metodi di estensione Linq esistenti funzionano su oggetti che attuare IEnumerable<T>. Presumo che il tuo oggetto implementa l'interfaccia non generica IEnumerable. In tal caso, è possibile utilizzare il metodo di estensione Cast<T> per ottenere un wrapper generico IEnumerable<T>. Per esempio, se gli elementi sono di tipo int:

var wrapper = myObject.Cast<int>(); 

è ora possibile utilizzare Linq su un involucro

0

No, non è possibile. Tutti i metodi LINQ sono metodi di estensione per l'interfaccia IEnumerable<T>.

Quindi sarà necessario implementare IEnumerable<T> per utilizzare LINQ con le proprie raccolte.

6

Non direttamente. Si potrebbe abbastanza facilmente scrivere un SingleShotEnumerable<T> però:

public sealed class SingleShotEnumerable<T> : IEnumerable<T> 
{ 
    private IEnumerator<T> enumerator; 

    public SingleShotEnumerable(IEnumerator<T> enumerator) 
    { 
     if (enumerator == null) 
     { 
      throw new ArgumentNullException("enumerator"); 
     } 
     this.enumerator = enumerator; 
    } 

    public IEnumerator<T> GetEnumerator() 
    { 
     if (enumerator == null) 
     { 
      throw new InvalidOperationException 
       ("GetEnumerator can only be called once"); 
     } 
     var ret = enumerator; 
     enumerator = null; 
     return ret; 
    } 

    IEnumerator IEnumerable.GetEnumerator() 
    { 
     return GetEnumerator(); 
    } 
} 

Questo si sta assumendo realtà hanno un IEnumerator<T>. Se hai solo IEnumerator, potresti scrivere qualcosa di simile implementando solo IEnumerable, quindi usa Cast o OfType per arrivare a un IEnumerable<T>.

(Nota: questo non è thread-safe Si potrebbe fare in modo con le serrature se si voleva davvero..)

È quindi possibile fare:

var filtered = from person in new SingleShotEnumerable<Person>(personEnumerator) 
       where person.Age > 18 
       select person.Name; 

... ma si couldn usare la query due volte

Come sei entrato nella strana situazione di avere solo uno IEnumerator<T>? Questo è abbastanza raro. Vedi se riesci a orientarti in modo da evitare di dover fare qualcosa come il precedente, che è piuttosto fragile.

(Un'alternativa sarebbe quella di "drain" del IEnumerator<T> ad un qualcosa List<T> o simile, ma che non ha problemi a gestire un grande o potenzialmente infinite sequenze.)

+0

Alcuni tipi 'System.Windows.Forms', come' ListViewItemCollection', non sembrano implementare 'IEnumerable '. –

+0

@ChrisAkridge: Effettivamente, implementano solo l'IEnumerable non generico. Ma puoi sempre chiamare 'Cast <>' per creare un 'IEnumerable ' da esso. –

Problemi correlati