2009-09-26 6 views
8

Quindi, molte volte abbiamo una funzione che accetta un IEnumerable o ICollection come parametro. Nei casi in cui abbiamo singole voci, ma nessuna raccolta di tenerli, dobbiamo creare una collezione prima di passarli alla funzione, come:Qual è il modo più semplice e compatto per creare un oggetto IEnumerable <T> o ICollection <T>?

T o1, o2, o3; 
Foo(new T[] { o1, o2, o3 }); 

Ho sempre creato un array o una lista, come I' ho fatto nell'ultimo esempio. Ma mi chiedo, c'è un modo più elegante per creare l'IEnumerable o ICollection richiesto?

Sarebbe piuttosto fresco, se si potesse fare questo:

Foo({ o1, o2, o3 }); 

e il compilatore creerebbe la possibile raccolta più astratto che avrebbe soddisfatto le esigenze di IEnumerable o ICollection (a seconda di quale la funzione accetta).

In ogni caso, come si passa o1, o2 e o3 a un parametro IEnumerable o ICollection?

risposta

10

La versione corrente di C# (3) supporta una notazione, senza esplicita del tipo, vale a dire

Foo(new [] { o1, o2, o3 }) 

per creare un array. C'è anche il Enumerable.Range di Linq per creare un intervallo continuo di numeri. Tutto il resto deve essere implementato. Nello spirito di Java:

public static IEnumerable<T> AsList<T>(params T[] values) { 
    return values; 
} 

di essere chiamato in questo modo:

Foo(Enumerable.AsList(o1, o2, o3)); 
+1

suggerisco 'AsList()' non è un buon nome per un metodo che restituisce un 'Enumerable', non' list'! Che ne dite di 'Enumerable.Create'? –

2

Supponendo Foo aspetta un IEnumerable <T>, è possibile usufruire di inferenza di tipo e fare:

T o1, o2, o3; 
Foo(new []{o1, o2, o3}); 
3

A volte ho usato un metodo con un argomento "params".

Foo(params T[] ts) 

E se sono determinata a IEnumerable devo solo che metodo delegato a quello che vuole IEnumerable.

Foo(params T[] ts) { Foo(ts.AsEnumerable()); } 

Devi chiamare AsEnumerable o stai andando a recurse.

2

Creazione di un array e passaggio che è probabilmente il modo più semplice/elegante per realizzare questo nella versione corrente di C#. È possibile usufruire di implicita tipizzazione array (cioè new[] { ... }, ma questo è quanto va

Ho il sospetto che stai veramente cercando il C# equivalente di questo # sintassi F:.

let foo = seq [ o1; o2; o3 ] 

che genera un IEnumerable<T> che andrà a scorrere sugli elementi specificati. ('Seq' è in realtà l'alias F # per 'IEnumerable`, sebbene F # abbia il supporto integrato per essi.)

Sfortunatamente, poiché questa è una nozione ampiamente funzionante, c'è nessun equivalente C# - anche se chissà quando sarà aggiunto, dato che C# diventa sempre più divertente finzionale.

0

Se si dispone di un metodo che accetta un array come ultimo parametro, può essere opportuno contrassegnare tale parametro params. In questo modo si chiama il metodo come questo:

Foo(o1, o2, o3); 

Ho trovato questo particolarmente utile quando si scrive un test di unità per Foo(), perché spesso in un'unità di prova i miei parametri sono separati come questo, invece che in un array.

Io sconsiglio di fare questo se c'è un sovraccarico di Foo() che non accetta un array in quella posizione, perché può creare confusione rapidamente.

mi auguro che il linguaggio C# permesso params per IList<T>:

void Foo(params IList<T> ts) { ... }