Warum musterbasierte Programmierung in C #

8

Ich frage mich, warum sich C # mehr auf Muster-basierte Programmierung als auf konventionelle Art und Weise bewegt.

Bsp. Die Anweisung foreach erwartet, dass die Schleifenquelle über eine magische Methode namens GetEnumerator verfügt, die ein Objekt zurückgibt, das einige weitere magische Methoden wie MoveNext und Current enthält, aber keine spezifische Schnittstelle vorgibt. C # könnte die Anweisung haben, dass eine in foreach zu verwendende Klasse IEnumerable oder IEnumerable<T> wie für die using -Anweisung implementieren soll, da sie erwartet, dass ein Objekt in der using -Anweisung verwendet wird, um% zu implementieren. co_de% interface.

Ich sehe auch einen ähnlichen Trend mit IDisposable / async -Schlüsselwörtern ....

Natürlich muss es einen guten Grund dafür geben, aber es scheint ein wenig seltsam für mich zu verstehen, warum Compiler / CLR "magische Methoden" erfordert, anstatt auf Schnittstellen angewiesen zu sein.

    
ConfusedCoder 12.01.2014, 02:36
quelle

1 Antwort

12

foreach

Ich würde sagen, es geht sowohl um Leistung als auch um Kompatibilität

  • Wenn Sie foreach gewählt hätten, um IEnumerable zu verwenden, hätten Sie alle generisch gemacht Collections Iteration sehr langsam für Werttypen T (wegen Boxen / Unboxing).
  • Wenn Sie IEnumerable<T> iterieren über ArrayList und verwendet hätten Alle nicht-generischen Sammlungen aus der frühen .NET-Version wären nicht möglich.

Ich denke, die Designentscheidung war gut. Wenn foreach eingeführt wurde (.NET 1.1), gab es in .NET nichts mit Generics (sie wurden in .NET 2.0 eingeführt). Wenn Sie IEnumerable als Quelle für foreach enumeration wählen, würde dies die Verwendung von generischen Sammlungen mindern oder eine radikale Änderung erfordern. Ich nehme an, Designer wussten bereits, dass sie nicht allzu lange später Generika einführen würden.

Zusätzlich deklarieren Sie es als Verwenden Sie IEnumerable<T> , wenn es verfügbar ist, oder IEnumerable , wenn es nicht ist nicht viel anders als verwenden Sie die verfügbare GetEnumerator -Methode oder kompilieren Sie sie nicht, wenn dies nicht der Fall ist verfügbar , oder?

aktualisieren

Wie @mikez in den Kommentaren erwähnt hat, gibt es einen weiteren Vorteil. Wenn Sie nicht erwarten, dass GetEnumerator IEnumerator / IEnumerator<T> zurückgibt, können Sie struct zurückgeben und sich nicht um das Boxen kümmern, wenn der Enumerator von loop verwendet wird.

LINQ

Die gleiche magische Methode -Situation tritt auf, wenn Sie LINQ- und Syntax-basierte Abfragen verwenden. Wenn Sie

schreiben %Vor%

es wird vom Compiler in

umgewandelt %Vor%

Und weil dieser Code funktionieren würde, egal welche Schnittstelle source implementiert, gilt das Gleiche für syntaxbasierte Abfragen. Solange nach der Umwandlung in eine methodenbasierte Abfrage kann jeder Methodenaufruf vom Compiler korrekt zugewiesen werden, alles ist in Ordnung.

asynchron / warten

Ich bin mir nicht so sicher, denke aber, dass das gleiche für async / await gilt. Wenn Sie diese Schlüsselwörter verwenden, generiert der Compiler eine Menge Code für sich selbst, der dann so kompiliert wird, als hätten Sie den Code selbst geschrieben. Und solange der von dieser Transformation erzeugte Code kompiliert werden kann, ist alles in Ordnung.

    
MarcinJuraszek 12.01.2014, 03:42
quelle

Tags und Links