Verwendung der Unveränderlichkeit in C #

Unveränderlichkeit ist eine Funktion funktionaler Programmiersprachen, die das Schreiben, Testen und Verwalten von Programmen erleichtert. Die Unveränderlichkeit wird jedoch von vielen wichtigen Programmiersprachen nicht unterstützt. Bis vor kurzem unterstützte C # die unveränderliche Unveränderlichkeit nicht. 

Dies ändert sich mit der Einführung von Datensätzen in C # 9, das in .NET 5 zur Vorschau verfügbar ist. Wir können jedoch die Unveränderlichkeit in früheren Versionen von C # mithilfe des Namespace System.Collections.Immutable implementieren, der als NuGet-Paket verfügbar ist. 

Ein unveränderliches Objekt ist ein Objekt, das nach seiner Erstellung nicht mehr geändert werden kann. Für viele Anwendungsfälle, wie z. B. Datenübertragungsobjekte, ist die Unveränderlichkeit ein wünschenswertes Merkmal. In diesem Artikel wird erläutert, warum wir die Unveränderlichkeit nutzen möchten und wie wir die Unveränderlichkeit in C # implementieren können.

Um mit den in diesem Artikel bereitgestellten Codebeispielen arbeiten zu können, muss Visual Studio 2019 auf Ihrem System installiert sein. Wenn Sie noch keine Kopie haben, können Sie Visual Studio 2019 hier herunterladen. 

Erstellen Sie ein .NET Core-Konsolenanwendungsprojekt in Visual Studio

Zunächst erstellen wir ein .NET Core-Konsolenanwendungsprojekt in Visual Studio. Angenommen, Visual Studio 2019 ist auf Ihrem System installiert, führen Sie die folgenden Schritte aus, um ein neues .NET Core-Konsolenanwendungsprojekt in Visual Studio zu erstellen.

  1. Starten Sie die Visual Studio-IDE.
  2. Klicken Sie auf "Neues Projekt erstellen".
  3. Wählen Sie im Fenster "Neues Projekt erstellen" aus der Liste der angezeigten Vorlagen "Konsolen-App (.NET Core)" aus.
  4. Weiter klicken. 
  5. Geben Sie im nächsten Fenster "Konfigurieren Sie Ihr neues Projekt" den Namen und den Speicherort für das neue Projekt an.
  6. Klicken Sie auf Erstellen. 

Dadurch wird ein neues .NET Core-Konsolenanwendungsprojekt in Visual Studio 2019 erstellt. Dieses Projekt wird in den folgenden Abschnitten dieses Artikels verwendet, um die Unveränderlichkeit zu veranschaulichen.

Installieren Sie das System.Collection.Immutable NuGet-Paket

Um mit unveränderlichen Typen zu arbeiten, sollten Sie das System.Collections.Immutable-Paket von NuGet installieren. Sie können dies entweder über den NuGet-Paketmanager in der Visual Studio 2019-IDE oder durch Ausführen des folgenden Befehls in der NuGet-Paketmanagerkonsole tun:

Install-Package System.Collections.Immutable

Dieses Paket enthält eine Sammlung von thread-sicheren Klassen, die auch als unveränderliche Sammlungen bezeichnet werden.

Unveränderlichkeit und Aufzeichnungen in C # 9 verstehen

Ein Datenübertragungsobjekt ist ein klassisches Beispiel dafür, wann Sie Unveränderlichkeit wünschen. Eine Instanz eines DTO wird häufig serialisiert, damit sie unabhängig von der auf Verbraucherseite verwendeten Technologie sein kann. Wenn Sie ein Datenobjekt zwischen einer Datenbank und einem Client übertragen, möchten Sie natürlich sicherstellen, dass das Objekt nicht geändert werden kann - und genau das ist der Zweck eines DTO. Weitere Informationen zur Verwendung von Datenübertragungsobjekten in C # finden Sie in meinem früheren Artikel hier. 

Um unveränderliche DTOs zu erstellen, können Sie eine ReadOnlyCollection oder die thread-sicheren unveränderlichen Auflistungstypen im System.Collections.Immutable-Namespace verwenden. Alternativ können Sie Datensatztypen in C # 9 nutzen, um unveränderliche DTOs zu implementieren.

Ein Datensatztyp in C # 9 ist ein leichter, unveränderlicher Datentyp (oder eine leichte Klasse), der nur schreibgeschützte Eigenschaften hat. Da ein Datensatztyp unveränderlich ist, ist er threadsicher und kann nach seiner Erstellung nicht mutiert oder geändert werden.

Sie können einen Datensatztyp nur innerhalb eines Konstruktors initialisieren. Das Erstellen eines Datensatztyps für eine Klasse (in diesem Beispiel Autor) ist so einfach wie das folgende Codeausschnitt.

Klassendaten Autor (int Id, Zeichenfolge Vorname, Zeichenfolge Nachname, Zeichenfolge Adresse);

Sie können den Datensatztyp des Autors auch wie im folgenden Codeausschnitt angegeben schreiben:

öffentliche Datenklasse Autor {

    public int Id {get; drin; }}

    öffentlicher String Vorname {get; drin; }}

    öffentlicher String lastName {get; drin; }}

    öffentliche Zeichenfolgenadresse {get; drin; }}

}}

Beachten Sie die Verwendung des Schlüsselworts data, wenn Sie den Datensatztyp deklarieren. Das Datenschlüsselwort, das in der Deklaration einer Klasse verwendet wird, markiert den Typ als Datensatz. Sie können eine Instanz des Datensatztyps nutzen, um Daten über die Ebenen zu übertragen und gleichzeitig die Unveränderlichkeit der DTOs sicherzustellen.

Der System.Collections.Immutable-Namespace

Unveränderliche Sammlungen sind solche, deren Mitglieder sich nach ihrer Erstellung nicht mehr ändern können. Der System.Collections.Immutable-Namespace umfasst mehrere unveränderliche Sammlungen. Dieser Namespace enthält unveränderliche Versionen von Listen, Wörterbüchern, Arrays, Hashes, Stacks und Queues.

Der ImmutableStack kann verwendet werden, um Elemente ähnlich wie bei veränderlichen Stacks zu verschieben und zu platzieren. Da ImmutableStack jedoch eine unveränderliche Sammlung ist, können ihre Elemente nicht geändert werden. Wenn Sie also die Pop-Methode aufrufen, um ein Element aus dem Stapel zu entfernen, wird ein neuer Stapel für Sie erstellt, und der ursprüngliche Stapel bleibt unverändert.

Lassen Sie uns dies anhand eines Beispiels veranschaulichen. Das folgende Codefragment zeigt, wie Sie Elemente auf einen unveränderlichen Stapel verschieben können.

var stack = ImmutableStack.Empty;

für (int i = 0; i <10; i ++)

{

    stack = stack.Push (i);

}}

Das folgende Programm zeigt, dass die Elemente eines unveränderlichen Stapels nicht geändert werden können.

Klassenprogramm

    {      

        statische Leere Main (string [] args)

        {

            var stack = ImmutableStack.Empty;

            für (int i = 0; i <10; i ++)

            {

                stack = stack.Push (i);

            }}

            Console.WriteLine ("Anzahl der Elemente im Originalstapel:

             "+ stack.Count ());

            var newStack = stack.Pop ();

            Console.WriteLine ("Anzahl der Elemente im neuen Stapel:" +

            newStack.Count ());

            Console.ReadKey ();

        }}

    }}

Wenn Sie das obige Programm ausführen, sollte die Ausgabe wie folgt im Konsolenfenster angezeigt werden.

Wie Sie in Abbildung 1 sehen können, bleibt der ursprüngliche unveränderliche Stapel (der 10 Elemente enthält) nach einem Aufruf der Pop () -Methode unverändert. Vielmehr wird ein neuer unveränderlicher Stapel mit 9 Elementen erstellt.

Unveränderliche Sammlungen bieten keine Konstruktoren, aber Sie können die statische Factory-Methode namens Create nutzen, wie im folgenden Code-Snippet gezeigt.

var list = ImmutableList.Create (1, 2, 3, 4, 5);

Wenn Sie ein Element zu dieser Sammlung hinzufügen oder daraus entfernen möchten, wird eine neue unveränderliche Liste erstellt und die ursprüngliche unveränderliche Liste bleibt unverändert.

Unveränderlichkeit ist eine Wahl des Designs; Dies bedeutet, dass eine Instanz eines Typs nach ihrer Erstellung nicht mehr geändert werden kann. Mit Ausnahme unveränderlicher Stapel und unveränderlicher Warteschlangen basieren alle unveränderlichen Sammlungen auf AVL-Bäumen. Daher können Sie Elemente an jeder Position der Sammlung einfügen, dh am Anfang, in der Mitte oder am Ende, ohne den Baum in seiner Gesamtheit kopieren zu müssen.

So machen Sie mehr in C #:

  • Verwendung von Datenanmerkungen in C #
  • So arbeiten Sie mit GUIDs in C # 8
  • Wann wird eine abstrakte Klasse im Vergleich zur Schnittstelle in C # verwendet?
  • So arbeiten Sie mit AutoMapper in C #
  • Verwendung von Lambda-Ausdrücken in C #
  • So arbeiten Sie mit Action-, Func- und Predicate-Delegaten in C #
  • So arbeiten Sie mit Delegierten in C #
  • So implementieren Sie einen einfachen Logger in C #
  • So arbeiten Sie mit Attributen in C #
  • So arbeiten Sie mit log4net in C #
  • So implementieren Sie das Repository-Entwurfsmuster in C #
  • Wie man mit Reflexion in C # arbeitet
  • So arbeiten Sie mit dem Dateisystemwatcher in C #
  • So führen Sie eine verzögerte Initialisierung in C # durch
  • So arbeiten Sie mit MSMQ in C #
  • So arbeiten Sie mit Erweiterungsmethoden in C #
  • Wie wir Lambda-Ausdrücke in C #
  • Wann wird das flüchtige Schlüsselwort in C # verwendet?
  • Verwendung des Schlüsselwortsield in C #
  • So implementieren Sie Polymorphismus in C #
  • So erstellen Sie Ihren eigenen Taskplaner in C #
  • So arbeiten Sie mit RabbitMQ in C #
  • So arbeiten Sie mit einem Tupel in C #
  • Erkundung virtueller und abstrakter Methoden in C #
  • Verwendung des Dapper ORM in C #
  • Verwendung des Entwurfsmusters im Fliegengewicht in C #