Du hast C# vor fünf oder zehn Jahren gelernt oder Du bis Newbie und deine Fachliteratur war nicht top-aktuell? Dann werden dich diese 8 Tipps überraschen. Microsoft hat in den letzten C# Versionen Features eingeführt, Boilerplates eliminieren, die Lesbarkeit verbessern und das tägliche Programmieren angenehmer machen.
Das Beste daran? Du musst nicht komplett umdenken. Es sind kleine, praktische Verbesserungen, die schnell zu deinem täglichen Handwerk werden. In diesem Artikel zeige ich Dir moderne C# Features, die dir helfen, sauberer und ausdrucksvoller Code mit weniger Zeilen zu schreiben.
1. Collection Expressions: C# Collections vereinfacht
Collection Expressions haben das Erstellen von Sammlungen in modernem C# eleganter gemacht. Früher sah das so aus:
|
1 2 3 4 5 6 7 |
List<string> fruits = new List<string> { "Apple", "Banana", "Orange" }; |
Heute schreiben wir einfach:
|
1 2 3 4 5 6 7 |
List<string> fruits = [ "Apple", "Banana", "Orange" ]; |
Oder mit Arrays:
|
1 2 3 4 5 6 7 8 |
int[] numbers = [ 10, 20, 30, 40 ]; |
Weniger Tipperei, sauberere Initialisierung, leichter zu lesen und einheitliche Syntax über alle Collection-Typen hinweg.
2. Primary Constructors: Weniger Boilerplate, mehr Klarheit
Konstruktoren existieren oft nur dazu, Parameter Feldern zuzuweisen. Das war schon immer etwas repetitiv:
|
1 2 3 4 5 6 7 8 9 10 |
public class ProductService { private readonly ILogger<ProductService> _logger; public ProductService(ILogger<ProductService> logger) { _logger = logger; } } |
Mit Primary Constructors wird das zu:
|
1 2 3 4 5 6 7 8 |
public class ProductService(ILogger<ProductService> logger) { public void Log() { logger.LogInformation("Hello"); } } |
Viel kürzer, sauberer und perfect für Dependency Injection.
Perfekt für:
- Services,
- Controller,
- Background Services
- Minimale APIs.
3. Required Members: Compile-Time Sicherheit
Wer hat das nicht schon erlebt? Du erstellst eine User-Klasse und vergisst später, die Name-Property zu setzen:
|
1 2 3 4 5 6 7 8 9 |
public class User { public string Name { get; set; } public string Email { get; set; } } // Später ... var user = new User(); // Oops! Keine Fehlermeldung |
Modernes C# behebt dieses Problem:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
public class User { public required string Name { get; set; } public required string Email { get; set; } } // Das kompiliert NICHT: var user = new User(); // Korrekt angewendet, kein Problem: // var user = new User { Name = "Ponting", Email = "ponting@email.com" }; |
Compile-Time Sicherheit statt Runtime-Überraschungen.
4. Raw String Literals: JSON und SQL ohne Escape-Chaos
Erinnere dich an diesen Alptraum:
|
1 2 |
string json = "{\"name\":\"Ponting\",\"age\":30}"; |
Raw String Literals ändern alles:
|
1 2 3 4 5 6 7 |
string json = """ { "name": "Ponting", "age": 30 } """; |
Auch SQL wird lesbarer:
|
1 2 3 4 5 6 |
string sql = """ SELECT * FROM Products WHERE Price > 100 """; |
Perfekt für:
- JSON,
- SQL,
- XML,
- HTML,
- Prompt Engineering
- Regex
5. Pattern Matching: Elegantere Bedingungen
Statt verschachtelter If-Statements:
|
1 2 3 4 5 6 7 |
if(employee != null && employee.Age >= 18 && employee.Department == "IT") { Console.WriteLine("Allowed"); } |
Schreiben wir einfach:
|
1 2 3 4 5 6 7 8 9 |
if(employee is { Age: >= 18, Department: "IT" }) { Console.WriteLine("Allowed"); } |
Es ist nicht nur ausdrucksvoller, es skaliert auch viel besser, wenn Bedingungen komplexer werden.
6. Target-Typed new: Weniger redundante Typangaben
Manchmal weiß der Compiler bereits, welcher Typ gemeint ist:
Alt:
|
1 2 |
Dictionary<int, string> users = new Dictionary<int, string>(); |
Modern:
|
1 2 |
Dictionary<int, string> users = new(); |
Es funktioniert wunderbar mit
- Listen,
- Dictionaries,
- Services,
- Records,
- Klassen generell.
7. File-Scoped Namespaces: Weniger Verschachtelung
Alt:
|
1 2 3 4 5 6 7 8 |
namespace MyApplication.Services { public class EmailService { ... } } |
Modern:
|
1 2 3 4 5 6 7 |
namespace MyApplication.Services; public class EmailService { ... } |
Vorteile:
Weniger Einrückung, sauberere Dateien und einfachere Navigation. Diese kleine Änderung macht in großen Projekten einen spürbaren Unterschied.
8. Global Using Directives: Das Endgame für Using-Statements
Wie viele Dateien beginnen so?
|
1 2 3 4 |
using System; using System.Linq; using Microsoft.Extensions.Logging; |
Statt diesen Code in hundert Dateien zu wiederholen, erstelle:
|
1 2 3 4 |
global using System; global using System.Linq; global using Microsoft.Extensions.Logging; |
Jetzt hat automatisch jede Datei Zugriff darauf.
Setze deine globalen Usings in eine UsingsGlobal.cs-Datei und vergiss sie. Weniger Boilerplate, mehr Konzentration auf echte Logik.
Fazit
Modernes C# handelt nicht davon, Komplexität hinzuzufügen. Der Schwerpunkt liegt darin, unnötige Code zu entfernen. Features wie Collection Expressions, Primary Constructors und Raw String Literals helfen dir, dich auf Business-Probleme zu konzentrieren statt auf Boilerplates.
Du musst nicht alle Features über Nacht adoptieren. Starte konsequent mit einem oder zwei. Bald werden sie sich völlig natürlich anfühlen, und du wirst dich fragen, wie du jemals anders C# geschrieben hast.
Kleine Sprachverbesserungen, konsistent angewendet, können einen großen Unterschied in der Lesbarkeit und Wartbarkeit deiner Codebasis ausmachen.
Happy Coding :-)
Mehr zum Thema C# gibt es hier