Servy richtig beantwortet Ihre Frage - eine Frage, die Sie sich in einem Kommentar geantwortet:
Ich habe erkannt, dass, da der Rückgabetyp eine Schnittstelle ist, wäre es ohnehin verpackt bekommen, ist das richtig?
Richtig. Ihre folgende Frage ist:
konnte die Methode nicht geändert werden, um einen explizit typisierten Enumerator zurückzugeben (wie List<T>
tut)?
Also hier Ihre Idee ist, dass der Benutzer schreibt:
IEnumerable<int> Blah() ...
und der Compiler generiert tatsächlich eine Methode, die BlahEnumerable
zurückgibt, die eine Struktur ist, die IEnumerable<int>
implementiert, aber mit der entsprechenden GetEnumerator
etc Methoden und Eigenschaften das erlaubt die "pattern matching" -Funktion von foreach
, um das Boxen zu elide.
Obwohl das eine plausible Idee ist, gibt es ernsthafte Schwierigkeiten, wenn Sie anfangen, über den Rückgabetyp einer Methode zu lügen. Insbesondere wenn es sich um eine Änderung handelt, ob die Methode eine Struktur oder einen Referenztyp zurückgibt. Denken Sie an all die Dinge, die schief gehen:
Angenommen, die Methode virtuell ist. Wie kann es außer Kraft gesetzt werden? Der Rückgabetyp einer virtuellen Überschreibungsmethode muss genau mit der überschriebenen Methode übereinstimmen. (Und ähnlich für: Die Methode überschreibt eine andere Methode, die Methode implementiert eine Methode einer Schnittstelle und so weiter.)
Angenommen, die Methode wird in einen Delegaten Func<IEnumerable<int>>
gemacht. Func<T>
ist kovariant in T
, aber Kovarianz gilt nur für Typargumente des Referenztyps.Der Code sieht aus wie es ein IEnumerable<T>
aber in der Tat gibt es gibt einen Wert, der nicht Kovarianz-kompatibel mit IEnumerable<T>
ist, nur Zuordnung kompatibel.
Angenommen, wir haben void M<T>(T t) where T : class
und wir rufen M(Blah())
. Wir gehen davon aus, abzuleiten, dass T
ist IEnumerable<int>
, die die Bedingungsprüfung passiert, aber der Strukturtyp hat nicht die Einschränkung Prüfung bestehen.
Und so weiter. Du landest schnell in einer Episode von Three's Company (Junge, mit der ich mich hier treffe), wo eine kleine Lüge sich zu einem großen Desaster zusammenfügt. All dies, um eine kleine Menge Sammeldruck zu sparen. Ist es nicht wert.
Ich bemerke jedoch, dass die durch den Compiler geschaffene Implementierung in einer interessanten Weise Sammeldruck spart. Das ersten Mal, dass GetEnumerator
auf dem zurück enumerable genannt wird, schaltet sich die zählbaren selbst in einen Enumerator. Beim zweiten Mal ist der Zustand natürlich anders, also weist er ein neues Objekt zu. Da das zu 99,99% wahrscheinliche Szenario ist, dass eine gegebene Sequenz genau einmal aufgelistet wird, ist dies eine große Ersparnis beim Sammeldruck.
Ich habe gerade festgestellt, dass, da der Rückgabetyp eine Schnittstelle (IEnumerable oder IEnumerator) ist, sie [http://stackoverflow.com/questions/3032750/] trotzdem gerahmt wird, ist das richtig? In diesem Fall könnte nicht die Methode geändert werden, um eine explizit eingegeben enumerator zurückzukehren (wie [List tut] (https://msdn.microsoft.com/en-us/library/b0yss765 (v = vs.110). aspx))? Da es die Schnittstellen implementiert, sollten alle Codereferenzen zu ihm beibehalten werden. (IIRC, dies funktioniert, weil 'foreach' wird [durch Muster erkannt] (https://blogs.msdn.microsoft.com/ericlippert/2011/06/30/following-the-pattern/)). –
Lazlo