Während die foreach
Konstrukts in C# und die For Each
Schleife in VB.NET werden häufig mit Typen verwendet, die IEnumerable<T>
implementieren, werden sie jede Art annehmen, die eine GetEnumerator
Methode, deren Rückgabetyp umfasst eine zutreffende MoveNext
Funktion und Current
Eigenschaft. Wenn Sie einen GetEnumerator
Rückgabewert zurückgeben, wird in vielen Fällen die Implementierung von foreach
effizienter, als dies bei einer Rückgabe von IEnumerator<T>
möglich wäre.
Leider, denn es gibt kein Mittel, mit dem ein Typ Wert-Typ Enumerator liefern kann, wenn sie von foreach
aufgerufen, ohne auch eine Versorgung, wenn sie von einem GetEnumerator
Methodenaufruf aufgerufen, die Autoren von List<T>
konfrontiert einen leichten Kompromiß der Leistung versus Semantik. Da C# zu diesem Zeitpunkt keine Inferenz vom Typ "Variable" unterstützt, müsste jeder Code, der den von List<T>.GetEnumerator
zurückgegebenen Wert verwendet, eine Variable vom Typ IEnumerator<T>
oder List<T>.Enumerator
deklarieren. Code, der den früheren Typ verwendet, würde sich so verhalten, als ob List<T>.Enumerator
ein Referenztyp wäre, und ein Programmierer, der letzteres verwendet, könnte annehmen, dass es sich um einen Strukturtyp handelt. Wenn C# Hinzufügung vom Typ hinzugefügt wurde, hörte diese Annahme jedoch auf zu halten. Code könnte sehr einfach mit dem Typ List<T>.Enumerator
enden, ohne dass der Programmierer von der Existenz dieses Typs weiß.
Wenn C# jemals ein struct-method-Attribut definieren würde, das zum Markieren von Methoden verwendet werden könnte, die in schreibgeschützten Strukturen nicht aufrufbar sein sollten, und wenn List<T>.Enumerator
davon Gebrauch macht, könnte Code wie Ihr ordnungsgemäß a liefern Kompilierzeitfehler beim Aufruf an MoveNext
eher das ergebende Scheinverhalten. Ich kenne jedoch keine besonderen Pläne, ein solches Attribut hinzuzufügen.
Ich schaue mir das an und habe Probleme herauszufinden, welches Element hier ein Werttyp ist, für den der Kopier-/Referenzunterschied tatsächlich einen Unterschied macht. –
Ich habe es nicht verstanden, wie es funktioniert, wenn wir es auf 'IEnumerable' '?? @ JonSkeet können Sie es mehr in einfachen Worten zu erklären –
@EhsanSajjad: Wenn der Compile-Time-Typ von 'TempList' ist IEnumerable', Zugriff darauf kopiert nur eine Referenz. Wenn Sie auf diese Referenz einwirken, wird der Boxed-Wert mutiert, und wenn Sie das nächste Mal eine Referenz kopieren, wird immer noch auf denselben Boxed-Wert Bezug genommen, sodass Sie die Änderung sehen. Vergleichen Sie das mit dem Kopieren des Werts des Werttyps und der Mutation dieser Kopie - wenn Sie * next * den ursprünglichen Wert kopieren, wird die vorherige Änderung nicht angezeigt. –