2013-07-15 11 views
5
  1. Ich habe eine generische Klasse A < T>, die IEnumerable < T implementiert []>.
  2. Ich möchte eine Bequemlichkeit Wrapper B haben, die von A < char erbt> und implementiert IEnumerable < String>.Multiple IEnumerable Implementierungen Paradox

    public class A<T> : IEnumerable<T[]> 
    { 
        public IEnumerator<T[]> GetEnumerator() 
        { 
         return Enumerate().GetEnumerator(); 
        } 
    
        IEnumerator IEnumerable.GetEnumerator() 
        { 
         return GetEnumerator(); 
        } 
    
        protected IEnumerable<T[]> Enumerate() 
        { 
         throw new System.NotImplementedException(); 
        } 
    } 
    
    public class B : A<char>, IEnumerable<string> 
    { 
        public IEnumerator<string> GetEnumerator() 
        { 
         return Enumerate().Select(s => new string(s)).GetEnumerator(); 
        } 
    
        IEnumerator IEnumerable.GetEnumerator() 
        { 
         return GetEnumerator(); 
        } 
    } 
    

Jetzt funktioniert das völlig in Ordnung, Variablentyp foreach wird gefolgert String sein:

B b = new B(); 
foreach (var s in b) 
{ 
    string[] split = s.Split(' '); 
} 

Aber dies wird nicht kompiliert, sagen: „Die Art Argumente können nicht von der Nutzung geschlossen werden , versuchen Sie die Typargumente explizit "festgelegt wird:

string[] strings = b.ToArray(); 

dies funktioniert jedoch:

string[] strings = b.ToArray<string>(); 

Kann jemand dieses Compilerverhalten erklären?

Offensichtlich implementiert B beide IEnumerable < char []> und IEnumerable < String> und wahrscheinlich kann es nicht herausfinden, wer von ihnen ich anrufen will, aber warum es funktioniert gut in „foreach“ Probe ?

Bitte, schlagen Sie mir nicht vor, mein Problem durch Komposition zu lösen - das ist der letzte Ausweg für mich.

Antwort

2

Der Unterschied ist folgender:

foreach sieht tatsächlich für eine öffentliche Methode namens GetEnumerator. Es interessiert nicht wirklich IEnumerable<T>. Ihre Klasse B hat nur eine öffentliche Methode namens GetEnumerator: Die in B definierte die in A definiert.

ToArray auf der anderen Seite ist eine Erweiterung Methode auf IEnumerable<T>. Da Ihre Klasse sowohl IEnumerable<string> als auch IEnumerable<char[]> ist, ist der Aufruf zwischen den beiden generischen Argumenten string und char[] nicht eindeutig.

2

foreach Schleife verwendet IEnumerable oder IEnumerable<T> Implementierung nicht. Sie können foreach verwenden, auch wenn Ihre Klasse keine davon implementiert. Das einzige, was es benötigt, ist GetEnumerator Methode, die IEnumerator Implementierung zurückgibt.

prüfen diese Frage: How is foreach implemented in C#?

Das ist, warum Ihre Klasse mit foreach arbeitet und nicht mit ToArray().