Einleitung: Zwei Seiten einer Medaille
\n\nStellen Sie sich vor, Sie bauen ein Haus. Sie können fertige Blöcke (Klassen, Objekte, Vererbung) nehmen und daraus eine komplexe Konstruktion zusammensetzen – das ist objektorientierte Programmierung (OOP). Oder Sie denken wie ein Mathematiker: "Ich nehme Daten, wende eine reine Funktion darauf an und erhalte ein neues Ergebnis, ohne etwas zu verändern" – das ist funktionale Programmierung.
\n\nIn C# koexistieren beide Paradigmen auf erstaunliche Weise. Und wenn Sie in dieser Sprache schreiben, werden Sie sich früher oder später fragen: "Was, wenn ich das falsch mache? Sollte ich mehr LINQ und weniger Klassen verwenden?"
\n\nIn diesem Artikel werden wir nicht darüber diskutieren, was besser ist. Wir werden verstehen, wie sich der funktionale Ansatz von OOP in C# unterscheidet, wann jeder von ihnen wirklich hilft und wann er schadet. Und ja, es wird viel Code geben. Los geht's!
\n\n1. OOP in C#: Ein Klassiker, der funktioniert
\n\nObjektorientierte Programmierung dreht sich um Zustand und Verhalten. Sie haben eine Klasse, die Daten (Felder, Eigenschaften) und Methoden speichert, die diese Daten ändern.
Beispiel: Eine Anwendung zur Verwaltung von Bestellungen in einem Online-Shop.
\n\npublic class Order\n{\n public int Id { get; set; }\n public List<string> Items { get; private set; }\n public decimal TotalPrice { get; private set; }\n\n public Order(int id)\n {\n Id = id;\n Items = new List<string>();\n TotalPrice = 0;\n }\n\n public void AddItem(string itemName, decimal price)\n {\n Items.Add(itemName);\n TotalPrice += price;\n }\n\n public void ApplyDiscount(decimal percent)\n {\n TotalPrice -= TotalPrice * (percent / 100);\n }\n}\n\nWas sehen wir? Kapselung: TotalPrice kann nicht direkt geändert werden – nur über Methoden. Der Zustand des Objekts ändert sich im Laufe der Zeit: Wir fügen Artikel hinzu, wenden Rabatte an. Das ist reine OOP.
Vorteile von OOP in C#
\n- \n
- Verständliches reales Modell: Bestellung, Kunde, Produkt – alles wie im echten Leben. \n
- Wiederverwendung durch Vererbung und Schnittstellen. \n
- Komplexitätsmanagement durch Aufteilung in kleine Objekte. \n
Nachteile von OOP
\n- \n
- Seiteneffekte: Eine Methode kann den Zustand ändern, und Sie verlieren leicht die Kontrolle. \n
- Testkomplexität: Sie müssen Objekte erstellen, Abhängigkeiten mocken. \n
- Redundanz: Manchmal ist es einfacher, eine Funktion zu schreiben, als eine ganze Klasse zu erstellen. \n
2. Funktionaler Ansatz in C#: LINQ und mehr
\n\nFunktionale Programmierung dreht sich um reine Funktionen (ohne Seiteneffekte) und Unveränderlichkeit von Daten. In C# ist dies besonders in LINQ, Lambda-Ausdrücken und der Arbeit mit Sammlungen sichtbar.
\n\nLassen Sie uns dieselbe Aufgabe lösen – die Verwaltung einer Bestellung – aber funktional.
\n\n// Unveränderlicher Datensatz (record)\npublic record Order(int Id, List<string> Items, decimal TotalPrice);\n\npublic static class OrderFunctions\n{\n public static Order AddItem(Order order, string item, decimal price)\n {\n var newItems = order.Items.Append(item).ToList();\n return order with { Items = newItems, TotalPrice = order.TotalPrice + price };\n }\n\n public static Order ApplyDiscount(Order order, decimal percent)\n {\n return order with { TotalPrice = order.TotalPrice * (1 - percent / 100) };\n }\n}\n\n// Verwendung\nvar order = new Order(1, new List<string>(), 0);\norder = OrderFunctions.AddItem(order, "Laptop", 50000);\norder = OrderFunctions.ApplyDiscount(order, 10);\n\nHaben Sie bemerkt? Wir ändern das ursprüngliche Objekt nicht. Jedes Mal wird mit with eine neue Instanz erstellt. Dies schließt versehentliche Änderungen aus.
Und