.NET Perché può uno string [] essere passato come IEnumerable parametro?
-
22-08-2019 - |
Domanda
Questo è un codice valido:
void func(IEnumerable<string> strings){
foreach(string s in strings){
Console.WriteLine(s);
}
}
string[] ss = new string[]{"asdf", "fdsa"};
func(ss);
Quello che voglio sapere è, come funziona il lavoro di conversione implicita string[] -> IEnumerable<string>
?
Soluzione
Nella versione di .NET Framework 2.0, della classe Array implementa il
IList<T>
,ICollection<T>
, eIEnumerable<T>
interfacce generiche. Le implementazioni sono fornito agli array in fase di esecuzione , e quindi non sono visibili agli strumenti di documentazione di compilazione. Come risultato, le interfacce generali non risultano nella sintassi di dichiarazione per la classe Array, e non vi sono argomenti di riferimento per elementi di interfaccia che sono accessibili solo per fusione un array del tipo interfaccia generica (implementazioni esplicite). La cosa fondamentale da essere a conoscenza di quando lanci un array per una di queste interfacce è che i membri che aggiungono, inserire o rimuovere elementi gettano
NotSupportedException
.
Altri suggerimenti
class Array
, che è una bestia strana ed è trattato molto speciale dal compilatore JIT e (più su che nei libri di Richter e Don Box di, credo), implementa IEnumerable<T>
.
Array implementano IEnumerable quindi per ogni T [] c'è una conversione IEnumerable
In che modo la stringa conversione implicita [] -> lavoro IEnumerable
Questo tipo di non coglie il punto, perché non c'è conversione. Array realizzare (si potrebbe quasi dire "ereditare da", se questo ha più senso per voi) IEnumerable, e così string [] già è un IEnumerable - non c'è niente di convertire
Questa è una conversione interfaccia standard; come requisito, array (T[]
) implementano IEnumerable
e IEnumerable<T>
. Quindi un string[]
è compatibile al 100% con IEnumerable<T>
. L'implementazione è fornito dal compilatore (array sono stati sostanzialmente generico prima esistevano farmaci generici NET).
Dal spec (ECMA 334 v4) - questa è una conseguenza di 13.1.4:
- Dal unidimensionale matrice di tipo
S[]
aSystem.Collections.Generic.IList<S>
e base interfacce di questa interfaccia. - Dal unidimensionale matrice di tipo
S[]
aSystem.Collections.Generic.IList<T>
e interfacce di base di questa interfaccia, purché vi sia una conversione riferimento implicito daS
aT
.
E ricordare che IList<T> : IEnumerable<T>