C#-Versionen: Was sich hinter den Zahlen verbirgt und wie es unter der Haube funktioniert
\n\nWenn Sie jemals in Diskussionen auf Stack Overflow gestöbert haben, haben Sie sicherlich die Frage gesehen, die tausende von Aufrufen gesammelt hat: "What are the correct version numbers for C#?". Man sollte meinen, was ist daran so schwer? Einfach die Dokumentation aufschlagen – und fertig. Aber in Wirklichkeit ist alles viel verwirrender. Besonders wenn sich herausstellt, dass C# 7.0 mit .NET Framework 4.7 erscheint und C# 8.0 bereits mit .NET Core 3.0. Und warum ist C# 5.0 überhaupt an keine bestimmte .NET-Version gebunden? Willkommen in einer Welt, in der Zahlen trügerisch sind.
\n\nIn diesem Artikel werden wir nicht einfach die Versionen auflisten. Wir werfen einen Blick unter die Haube des Roslyn-Compilers, verstehen, wie die Versionsnummern mit den Plattformen zusammenhängen, und zeigen anhand von echten Codebeispielen, welche Features in jeder Version hinzugekommen sind. Los geht's!
\n\nWarum ist die Frage nach den C#-Versionen so beliebt?
\n\nDie Antwort ist einfach: Verwechslung zwischen den Versionen der Sprache C# und den Versionen von .NET. Viele Entwickler denken, dass C# 7.0 dasselbe ist wie .NET Framework 4.7. Aber das stimmt nicht. Die Sprache C# führt ihr eigenes Leben, und die Plattform .NET führt ihres. Der Roslyn-Compiler (auch bekannt als csc.exe) ist die Brücke zwischen ihnen. Er nimmt C#-Code und wandelt ihn in IL-Code (Intermediate Language) um, der dann von der CLR (Common Language Runtime) ausgeführt wird.
Hier ist der entscheidende Punkt: Ein und dieselbe Compiler-Version kann verschiedene Sprachversionen unterstützen. Zum Beispiel kann der Compiler aus Visual Studio 2019 Code in C# 7.0, 7.1, 7.2, 7.3, 8.0 kompilieren – abhängig von den Projekteinstellungen. Genau deshalb gibt es auf Stack Overflow so viel Verwirrung.
\n\nKurze Geschichte der C#-Versionen
\n\nLassen Sie uns die wichtigsten Meilensteine durchgehen. Ich werde nicht alle 12 Versionen der Reihe nach auflisten – sondern lieber die hervorheben, die das Spiel wirklich verändert haben.
\n\nC# 1.0 (2002) – Der Anfang
\nDie erste Version der Sprache erschien zusammen mit .NET Framework 1.0. Es war eine managed-Sprache mit einer an Java angelehnten Syntax, aber mit einzigartigen Features wie Properties und Indexern. Kein LINQ, kein async/await, keine Generics. Einfach, zuverlässig, langweilig.
\n\nC# 2.0 (2005) – Generics verändern alles
\nMit dieser Version kamen Generics, anonyme Methoden, Iteratoren (yield return) und partielle Klassen. Das war ein Durchbruch: Anstatt ArrayList mit Boxing/Unboxing zu schreiben, konnten Sie List<T> verwenden. Die Leistung schoss in die Höhe.
// C# 2.0 – Generics\nList<int> numbers = new List<int> { 1, 2, 3 };\nnumbers.ForEach(n => Console.WriteLine(n * 2)); // Anonyme Methode\n\n\nC# 3.0 (2007) – LINQ und Lambdas
\nDie revolutionärste Version. LINQ (Language Integrated Query) veränderte den Umgang mit Daten. Lambda-Ausdrücke, Erweiterungsmethoden, anonyme Typen, Objektinitialisierer – all das kam hier hinzu. Der Roslyn-Compiler war damals noch nicht geboren, aber in C# 3.0 wurden die Grundlagen für die Zukunft gelegt.
\n\n// C# 3.0 – LINQ und Lambdas\nvar evenNumbers = Enumerable.Range(1, 10)\n .Where(x => x % 2 == 0)\n .Select(x => x * x);\nConsole.WriteLine(string.Join(", ", evenNumbers)); // 4, 16, 36, 64, 100\n\n\nC# 5.0 (2012) – Async/await
\nAsynchrone Programmierung wurde so einfach wie nie zuvor. async und await sind nicht nur syntaktischer Zucker. Der Compiler generiert eine komplexe State Machine, die die Threads verwaltet. Wenn Sie in C# 5.0 und höher schreiben, können Sie die manuelle Verwaltung von BeginInvoke und EndInvoke vergessen.
// C# 5.0 – async/await\nasync Task<string> FetchDataAsync(string url)\n{\n using (var client = new HttpClient())\n {\n return await client.GetStringAsync(url);\n }\n}\n\n\nC# 6.0 (2015) – Zucker für den Alltag
\nDiese Version brachte keine neuen Paradigmen, machte den Code aber sauberer: String-Interpolation