Jak używać niezmienności w C #

Niezmienność to cecha funkcjonalnych języków programowania, która ułatwia pisanie, testowanie i konserwację programów. Jednak niezmienność nie jest obsługiwana przez wiele imperatywnych języków programowania. Do niedawna C # nie obsługiwał niezmienności po wyjęciu z pudełka. 

Zmienia się to wraz z wprowadzeniem rekordów w języku C # 9, który jest dostępny do podglądu w .NET 5. Możemy jednak zaimplementować niezmienność we wcześniejszych wersjach C # przy użyciu przestrzeni nazw System.Collections.Immutable, która jest dostępna jako pakiet NuGet. 

Niezmienny obiekt jest definiowany jako obiekt, którego nie można zmienić po utworzeniu. W wielu przypadkach użycia, takich jak obiekty transferu danych, niezmienność jest pożądaną funkcją. W tym artykule omówiono, dlaczego możemy chcieć skorzystać z niezmienności i jak możemy zaimplementować niezmienność w języku C #.

Aby pracować z przykładami kodu przedstawionymi w tym artykule, w systemie powinien być zainstalowany program Visual Studio 2019. Jeśli nie masz jeszcze kopii, możesz pobrać program Visual Studio 2019 tutaj. 

Utwórz projekt aplikacji konsoli .NET Core w programie Visual Studio

Po pierwsze, utwórzmy projekt aplikacji konsoli .NET Core w programie Visual Studio. Zakładając, że w systemie jest zainstalowany program Visual Studio 2019, wykonaj czynności opisane poniżej, aby utworzyć nowy projekt aplikacji konsoli .NET Core w programie Visual Studio.

  1. Uruchom środowisko IDE programu Visual Studio.
  2. Kliknij „Utwórz nowy projekt”.
  3. W oknie „Utwórz nowy projekt” wybierz „Aplikacja konsoli (.NET Core)” z wyświetlonej listy szablonów.
  4. Kliknij Następny. 
  5. W oknie „Konfiguruj nowy projekt” pokazanym obok podaj nazwę i lokalizację nowego projektu.
  6. Kliknij Utwórz. 

Spowoduje to utworzenie nowego projektu aplikacji konsoli .NET Core w programie Visual Studio 2019. Użyjemy tego projektu do zilustrowania niezmienności w kolejnych sekcjach tego artykułu.

Zainstaluj pakiet System.Collection.Immutable NuGet

Aby pracować z niezmiennymi typami, należy zainstalować pakiet System.Collections.Immutable z NuGet. Możesz to zrobić za pośrednictwem menedżera pakietów NuGet w środowisku IDE programu Visual Studio 2019 lub wykonując następujące polecenie w konsoli Menedżera pakietów NuGet:

Zainstaluj pakiet System.Collections.Immutable

Ten pakiet zawiera kolekcję klas bezpiecznych dla wątków, zwanych również kolekcjami niezmiennymi.

Zrozum niezmienność i rekordy w języku C # 9

Obiekt transferu danych jest klasycznym przykładem niezmienności. Wystąpienie DTO jest często serializowane, dzięki czemu może być niezależne od technologii używanej po stronie konsumenta. Oczywiście, przesyłając obiekt danych między bazą danych a klientem, chciałbyś mieć pewność, że obiektu nie można zmienić - i to jest dokładnie celem DTO. Możesz przeczytać więcej o korzystaniu z obiektów transferu danych w C # z mojego wcześniejszego artykułu tutaj. 

Aby utworzyć niezmienne DTO, można skorzystać z ReadOnlyCollection lub niezmiennych typów kolekcji bezpiecznych dla wątków w przestrzeni nazw System.Collections.Immutable. Alternatywnie możesz skorzystać z typów rekordów w języku C # 9, aby zaimplementować niezmienne DTO.

Typ rekordu w C # 9 to lekki, niezmienny typ danych (lub lekka klasa), który ma właściwości tylko do odczytu. Ponieważ typ rekordu jest niezmienny, jest bezpieczny dla wątków i nie można go mutować ani zmieniać po utworzeniu.

Typ rekordu można zainicjować tylko w konstruktorze. Tworzenie typu rekordu dla klasy (w tym przykładzie Autor) jest tak proste, jak poniższy fragment kodu.

klasa data Author (int Id, string firstName, string lastName, string address);

Możesz również napisać typ rekordu Autor, jak pokazano we fragmencie kodu podanym poniżej:

public data class Autor {

    public int Id {get; w tym; }

    public string firstName {get; w tym; }

    public string lastName {get; w tym; }

    public string address {get; w tym; }

}

Zwróć uwagę na użycie słowa kluczowego data podczas deklarowania typu rekordu. Słowo kluczowe data użyte w deklaracji klasy oznacza typ jako rekord. Możesz skorzystać z wystąpienia typu rekordu, aby przekazać dane między warstwami, zapewniając jednocześnie niezmienność DTO.

Przestrzeń nazw System.Collections.Immutable

Niezmienne kolekcje to takie, których członkowie nie mogą zmienić się po ich utworzeniu. Przestrzeń nazw System.Collections.Immutable zawiera kilka niezmiennych kolekcji. Ta przestrzeń nazw zawiera niezmienne wersje list, słowników, tablic, skrótów, stosów i kolejek.

ImmutableStack może służyć do wypychania i popychania elementów w taki sam sposób, jak w przypadku stosów mutowalnych. Jednak ponieważ ImmutableStack jest niezmienną kolekcją, nie można zmienić jej elementów. Tak więc, kiedy wywołujesz metodę pop, aby zdjąć element ze stosu, tworzony jest nowy stos, a oryginalny stos pozostaje niezmieniony.

Zilustrujmy to przykładem. Poniższy fragment kodu pokazuje, jak można wypychać elementy na niezmienny stos.

var stack = ImmutableStack.Empty;

dla (int i = 0; i <10; i ++)

{

    stack = stack.Push (i);

}

Poniższy program demonstruje, że nie można zmienić elementów niezmiennego stosu.

Program zajęć

    {      

        static void Main (string [] args)

        {

            var stack = ImmutableStack.Empty;

            dla (int i = 0; i <10; i ++)

            {

                stack = stack.Push (i);

            }

            Console.WriteLine ("Liczba elementów w oryginalnym stosie:

             "+ stack.Count ());

            var newStack = stack.Pop ();

            Console.WriteLine ("Liczba elementów w nowym stosie:" +

            newStack.Count ());

            Console.ReadKey ();

        }

    }

Po uruchomieniu powyższego programu, oto jak wyjście powinno wyglądać w oknie konsoli.

Jak widać na rysunku 1, oryginalny niezmienny stos (zawierający 10 elementów) pozostaje niezmieniony po wywołaniu metody Pop (). Zamiast tego tworzony jest nowy niezmienny stos z 9 elementami.

Niezmienne kolekcje nie oferują konstruktorów, ale można skorzystać ze statycznej metody fabryki o nazwie Create, jak pokazano we fragmencie kodu podanym poniżej.

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

Jeśli chcesz dodać lub usunąć element z tej kolekcji, zostanie utworzona nowa niezmienna lista, a oryginalna niezmienna lista pozostanie niezmieniona.

Niezmienność to wybór projektu; oznacza to, że instancji typu nie można zmienić po jej utworzeniu. Z wyjątkiem niezmiennych stosów i niezmiennych kolejek, wszystkie niezmienne kolekcje są oparte na drzewach AVL. W związku z tym możesz wstawiać elementy w dowolnym miejscu kolekcji, tj. Na początku, w środku lub na końcu, bez konieczności kopiowania całego drzewa.

Jak zrobić więcej w C #:

  • Jak używać adnotacji danych w C #
  • Jak pracować z identyfikatorami GUID w C # 8
  • Kiedy używać klasy abstrakcyjnej, a kiedy interfejsu w języku C #
  • Jak pracować z AutoMapper w C #
  • Jak używać wyrażeń lambda w C #
  • Jak pracować z delegatami Action, Func i Predicate w C #
  • Jak pracować z delegatami w C #
  • Jak zaimplementować prosty rejestrator w C #
  • Jak pracować z atrybutami w C #
  • Jak pracować z log4net w C #
  • Jak zaimplementować wzorzec projektu repozytorium w C #
  • Jak pracować z odbiciem w C #
  • Jak pracować z Filesystemwatcher w C #
  • Jak wykonać leniwą inicjalizację w C #
  • Jak pracować z MSMQ w C #
  • Jak pracować z metodami rozszerzającymi w C #
  • Jak nam wyrażenia lambda w C #
  • Kiedy używać słowa kluczowego volatile w języku C #
  • Jak używać słowa kluczowego yield w języku C #
  • Jak zaimplementować polimorfizm w C #
  • Jak zbudować własny harmonogram zadań w C #
  • Jak pracować z RabbitMQ w C #
  • Jak pracować z krotką w C #
  • Eksplorowanie metod wirtualnych i abstrakcyjnych w C #
  • Jak korzystać z Dapper ORM w C #
  • Jak używać wzorca projektowego flyweight w C #