Comment utiliser l'immuabilité en C #

L'immuabilité est une fonctionnalité des langages de programmation fonctionnels qui facilite l'écriture, le test et la maintenance des programmes. Cependant, l'immuabilité n'est pas prise en charge par de nombreux langages de programmation impératifs. Jusqu'à récemment, C # ne prenait pas en charge l'immuabilité prête à l'emploi. 

Cela change avec l'introduction d'enregistrements en C # 9, qui est disponible pour l'aperçu dans .NET 5. Cependant, nous pouvons implémenter l'immuabilité dans les versions antérieures de C # en utilisant l'espace de noms System.Collections.Immutable, qui est disponible en tant que package NuGet. 

Un objet immuable est défini comme un objet qui ne peut pas être modifié après sa création. Pour de nombreux cas d'utilisation, tels que les objets de transfert de données, l'immuabilité est une fonctionnalité souhaitable. Cet article explique pourquoi nous pourrions vouloir tirer parti de l'immuabilité et comment nous pouvons implémenter l'immuabilité en C #.

Pour utiliser les exemples de code fournis dans cet article, vous devez disposer de Visual Studio 2019 installé sur votre système. Si vous n'en avez pas déjà une copie, vous pouvez télécharger Visual Studio 2019 ici. 

Créer un projet d'application console .NET Core dans Visual Studio

Tout d'abord, créons un projet d'application console .NET Core dans Visual Studio. En supposant que Visual Studio 2019 est installé sur votre système, suivez les étapes décrites ci-dessous pour créer un nouveau projet d'application console .NET Core dans Visual Studio.

  1. Lancez l'IDE de Visual Studio.
  2. Cliquez sur "Créer un nouveau projet".
  3. Dans la fenêtre «Créer un nouveau projet», sélectionnez «Application console (.NET Core)» dans la liste des modèles affichés.
  4. Cliquez sur Suivant. 
  5. Dans la fenêtre «Configurer votre nouveau projet» ci-dessous, spécifiez le nom et l'emplacement du nouveau projet.
  6. Cliquez sur Créer. 

Cela créera un nouveau projet d'application console .NET Core dans Visual Studio 2019. Nous utiliserons ce projet pour illustrer l'immuabilité dans les sections suivantes de cet article.

Installez le package NuGet System.Collection.Immutable

Pour travailler avec des types immuables, vous devez installer le package System.Collections.Immutable de NuGet. Vous pouvez le faire via le gestionnaire de packages NuGet dans l'IDE de Visual Studio 2019 ou en exécutant la commande suivante dans la console du gestionnaire de packages NuGet:

Système de package d'installation.Collections.Immuable

Ce package comprend une collection de classes thread-safe, également appelées collections immuables.

Comprendre l'immuabilité et les enregistrements en C # 9

Un objet de transfert de données est un exemple classique du moment où vous voulez l'immuabilité. Une instance d'un DTO est souvent sérialisée afin qu'elle puisse être indépendante de la technologie utilisée du côté du consommateur. Naturellement, lors du transfert d'un objet de données entre une base de données et un client, vous souhaitez vous assurer que l'objet ne peut pas être modifié - et c'est exactement le but d'un DTO. Vous pouvez en savoir plus sur l'utilisation des objets de transfert de données en C # dans mon article précédent ici. 

Pour créer des DTO immuables, vous pouvez tirer parti d'un ReadOnlyCollection ou des types de collection immuables thread-safe dans l'espace de noms System.Collections.Immutable. Vous pouvez également tirer parti des types d'enregistrement en C # 9 pour implémenter des DTO immuables.

Un type d'enregistrement en C # 9 est un type de données léger et immuable (ou une classe légère) qui n'a que des propriétés en lecture seule. Étant donné qu'un type d'enregistrement est immuable, il est thread-safe et ne peut pas muter ou changer une fois qu'il a été créé.

Vous ne pouvez initialiser un type d'enregistrement qu'à l'intérieur d'un constructeur. La création d'un type d'enregistrement pour une classe (Author dans cet exemple) est aussi simple que l'extrait de code suivant.

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

Vous pouvez également écrire le type d'enregistrement Auteur comme indiqué dans l'extrait de code ci-dessous:

classe de données publiques Auteur {

    public int Id {get; init; }

    chaîne publique firstName {get; init; }

    chaîne publique lastName {get; init; }

    adresse de chaîne publique {get; init; }

}

Notez l'utilisation du mot-clé data lors de la déclaration du type d'enregistrement. Le mot clé data lorsqu'il est utilisé dans la déclaration d'une classe marque le type comme un enregistrement. Vous pouvez profiter d'une instance de type d'enregistrement pour transmettre des données à travers les couches tout en garantissant l'immuabilité des DTO.

L'espace de noms System.Collections.Immutable

Les collections immuables sont celles dont les membres ne peuvent pas changer une fois qu'ils ont été créés. L'espace de noms System.Collections.Immutable comprend plusieurs collections immuables. Cet espace de noms contient des versions immuables de Lists, Dictionaries, Arrays, Hashes, Stacks et Queues.

ImmutableStack peut être utilisé pour pousser et pop des éléments de la même manière que nous le faisons avec des piles mutables. Cependant, étant donné qu'ImmutableStack est une collection immuable, ses éléments ne peuvent pas être modifiés. Ainsi, lorsque vous appelez la méthode pop pour extraire un élément de la pile, une nouvelle pile est créée pour vous et la pile d'origine reste inchangée.

Illustrons cela avec un exemple. L'extrait de code suivant montre comment vous pouvez pousser des éléments sur une pile immuable.

var stack = ImmutableStack.Empty;

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

{

    pile = pile.Pousser (i);

}

Le programme suivant montre que les éléments d'une pile immuable ne peuvent pas être modifiés.

programme de classe

    {      

        static void Main (string [] args)

        {

            var pile = ImmutableStack.Empty;

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

            {

                pile = pile.Pousser (i);

            }

            Console.WriteLine ("Nombre d'éléments dans la pile d'origine:

             "+ stack.Count ());

            var newStack = pile.Pop ();

            Console.WriteLine ("Nombre d'éléments dans la nouvelle pile:" +

            newStack.Count ());

            Console.ReadKey ();

        }

    }

Lorsque vous exécutez le programme ci-dessus, voici comment la sortie doit apparaître dans la fenêtre de la console.

Comme vous pouvez le voir sur la figure 1, la pile immuable d'origine (contenant 10 éléments) est inchangée après un appel à la méthode Pop (). Au contraire, une nouvelle pile immuable est créée avec 9 éléments.

Les collections immuables n'offrent pas de constructeurs, mais vous pouvez tirer parti de la méthode de fabrique statique appelée Create comme indiqué dans l'extrait de code ci-dessous.

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

Si vous vouliez ajouter ou supprimer un élément de cette collection, une nouvelle liste immuable serait créée et la liste immuable d'origine resterait inchangée.

L'immuabilité est un choix de conception; cela signifie qu'une instance d'un type ne peut pas être modifiée après sa création. À l'exception des piles immuables et des files d'attente immuables, toutes les collections immuables sont basées sur des arborescences AVL. Vous pouvez donc insérer des éléments à n'importe quelle position de la collection, c'est-à-dire au début, au milieu ou à la fin, sans avoir besoin de copier l'arborescence dans son intégralité.

Comment faire plus en C #:

  • Comment utiliser les annotations de données en C #
  • Comment travailler avec les GUID en C # 8
  • Quand utiliser une classe abstraite ou une interface en C #
  • Comment travailler avec AutoMapper en C #
  • Comment utiliser les expressions lambda en C #
  • Comment travailler avec les délégués Action, Func et Predicate en C #
  • Comment travailler avec des délégués en C #
  • Comment implémenter un simple logger en C #
  • Comment travailler avec des attributs en C #
  • Comment travailler avec log4net en C #
  • Comment implémenter le modèle de conception de référentiel en C #
  • Comment travailler avec la réflexion en C #
  • Comment travailler avec Filesystemwatcher en C #
  • Comment effectuer une initialisation différée en C #
  • Comment travailler avec MSMQ en C #
  • Comment travailler avec des méthodes d'extension en C #
  • Comment utiliser les expressions lambda en C #
  • Quand utiliser le mot clé volatile en C #
  • Comment utiliser le mot clé yield en C #
  • Comment implémenter le polymorphisme en C #
  • Comment créer votre propre planificateur de tâches en C #
  • Comment travailler avec RabbitMQ en C #
  • Comment travailler avec un tuple en C #
  • Explorer les méthodes virtuelles et abstraites en C #
  • Comment utiliser l'ORM Dapper en C #
  • Comment utiliser le modèle de conception de poids mouche en C #