Menu
Coddy logo textTech

Immutability-Muster

Teil des Abschnitts Objektorientierte Programmierung der C#-Journey von Coddy — Lektion 34 von 70.

Unveränderlichkeit führt die Kapselung zu ihrem logischen Extrem – sobald ein Objekt erstellt wurde, kann es sich nie mehr ändern. Dies eliminiert ganze Kategorien von Fehlern, da Sie sich nie Sorgen machen müssen, dass etwas Ihre Daten unerwartet ändert.

Der einfachste Weg, eine unveränderliche Klasse zu erstellen, besteht darin, readonly-Felder mit einem Konstruktor zu verwenden, der alle Werte setzt, und keine Setter bereitzustellen:

public class Point
{
    public readonly int X;
    public readonly int Y;
    
    public Point(int x, int y)
    {
        X = x;
        Y = y;
    }
}

Sobald ein Point erstellt wurde, können seine Koordinaten nicht mehr geändert werden. Aber was ist, wenn Sie eine modifizierte Version benötigen? Anstatt das bestehende Objekt zu ändern, geben Sie ein neues zurück:

public Point Move(int deltaX, int deltaY)
{
    return new Point(X + deltaX, Y + deltaY);
}

Der ursprüngliche Punkt bleibt unverändert, während Sie einen neuen Punkt mit aktualisierten Werten erhalten. Dieses Muster wird in ganz .NET verwendet – Strings zum Beispiel sind unveränderlich. Wenn Sie ToUpper() aufrufen, erhalten Sie einen neuen String, anstatt den ursprünglichen zu ändern.

Unveränderliche Objekte sind von Natur aus threadsicher, da kein Code sie nach der Erstellung modifizieren kann. Sie sind zudem einfacher zu verstehen, da man weiß, dass sich ihr Zustand niemals unerwartet ändern wird.

challenge icon

Aufgabe

Einfach

Lassen Sie uns ein unveränderliches (immutable) Geldsystem aufbauen, das zeigt, wie Objekte so entworfen werden können, dass sie sich nach der Erstellung nie mehr ändern. Sie werden eine Money-Klasse erstellen, bei der jede Operation ein neues Objekt zurückgibt, anstatt das ursprüngliche zu ändern – ein Muster, das Ihren Code sicherer und leichter nachvollziehbar macht.

Sie werden Ihren Code in zwei Dateien organisieren:

  • Money.cs: Erstellen Sie eine unveränderliche Money-Klasse im Namespace Finance. Ihr Geld-Objekt sollte Folgendes haben:
    • Zwei readonly-Felder: Amount (decimal) und Currency (string)
    • Einen Konstruktor, der beide Werte setzt – einmal erstellt, kann sich ein Money-Objekt nie mehr ändern
    • Eine Methode Add(decimal value), die ein neues Money-Objekt mit dem erhöhten Betrag (gleiche Währung) zurückgibt
    • Eine Methode Subtract(decimal value), die ein neues Money-Objekt mit dem verringerten Betrag (gleiche Währung) zurückgibt
    • Eine Methode Convert(string newCurrency, decimal rate), die ein neues Money-Objekt zurückgibt, bei dem der Betrag mit dem Kurs multipliziert wurde und die neue Währung gesetzt ist
    • Eine Methode GetDisplay(), die einen String im Format "{Amount} {Currency}" zurückgibt
    Denken Sie daran: Keine dieser Methoden sollte das ursprüngliche Objekt verändern – sie alle geben brandneue Money-Instanzen zurück!
  • Program.cs: Demonstrieren Sie in Ihrer Hauptdatei die Unveränderlichkeit in Aktion. Erstellen Sie ein anfängliches Money-Objekt und führen Sie dann Operationen damit aus, während Sie Referenzen sowohl auf das Original als auch auf die Ergebnisse behalten. Dies wird beweisen, dass sich das Original auch nach mehreren Operationen nie ändert.

Sie erhalten vier Eingaben:

  • Anfangsbetrag (decimal)
  • Anfangswährung (string)
  • Hinzuzufügender Betrag (decimal)
  • Umrechnungskurs zu EUR (decimal)

Geben Sie die Ausgabe in diesem Format aus:

Original: {GetDisplay()}
After add: {GetDisplay()}
Original unchanged: {GetDisplay()}
Converted: {GetDisplay()}

Wenn die Eingaben beispielsweise 100.00, USD, 50.00 und 0.85 sind, sollte die Ausgabe wie folgt aussehen:

Original: 100.00 USD
After add: 150.00 USD
Original unchanged: 100.00 USD
Converted: 127.50 EUR

Beachten Sie, dass das ursprüngliche Money-Objekt auch nach dem Aufruf von Add() immer noch 100.00 USD anzeigt – das ist Unveränderlichkeit! Die Methode Add() hat ein völlig neues Objekt mit 150.00 USD erstellt und das Original unberührt gelassen. Die Umrechnung wird auf das Ergebnis der Add-Operation angewendet.

Spickzettel

Unveränderlichkeit (Immutability) bedeutet, dass ein Objekt nach seiner Erstellung niemals geändert werden kann. Dies eliminiert Fehler, die mit unerwarteten Datenänderungen zusammenhängen.

Erstellen Sie eine unveränderliche Klasse unter Verwendung von readonly-Feldern mit einem Konstruktor und ohne Setter:

public class Point
{
    public readonly int X;
    public readonly int Y;
    
    public Point(int x, int y)
    {
        X = x;
        Y = y;
    }
}

Um ein unveränderliches Objekt zu modifizieren, geben Sie eine neue Instanz zurück, anstatt die bestehende zu ändern:

public Point Move(int deltaX, int deltaY)
{
    return new Point(X + deltaX, Y + deltaY);
}

Vorteile von unveränderlichen Objekten:

  • Thread-sicher durch Design, da kein Code sie nach der Erstellung ändern kann
  • Einfacher nachzuvollziehen, da sich ihr Zustand nie unerwartet ändert
  • Werden überall in .NET verwendet (z. B. sind Strings unveränderlich)

Probier es selbst

using System;
using Finance;

class Program
{
    public static void Main(string[] args)
    {
        // Eingaben lesen
        decimal initialAmount = Convert.ToDecimal(Console.ReadLine());
        string initialCurrency = Console.ReadLine();
        decimal amountToAdd = Convert.ToDecimal(Console.ReadLine());
        decimal conversionRate = Convert.ToDecimal(Console.ReadLine());

        // TODO: Erstelle ein initiales Money-Objekt mit dem ursprünglichen Betrag und der Währung

        // TODO: Gib das ursprüngliche Geld mit GetDisplay() aus

        // TODO: Rufe Add() auf dem Original auf und speichere das Ergebnis in einer neuen Variable

        // TODO: Gib das Ergebnis nach dem Hinzufügen mit GetDisplay() aus

        // TODO: Gib das Original erneut aus, um zu beweisen, dass es unverändert ist

        // TODO: Konvertiere das addierte Ergebnis unter Verwendung des Umrechnungskurses in EUR

        // TODO: Gib das konvertierte Geld mit GetDisplay() aus
    }
}
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung