IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Vous êtes nouveau sur Developpez.com ? Créez votre compte ou connectez-vous afin de pouvoir participer !

Vous devez avoir un compte Developpez.com et être connecté pour pouvoir participer aux discussions.

Vous n'avez pas encore de compte Developpez.com ? Créez-en un en quelques instants, c'est entièrement gratuit !

Si vous disposez déjà d'un compte et qu'il est bien activé, connectez-vous à l'aide du formulaire ci-dessous.

Identifiez-vous
Identifiant
Mot de passe
Mot de passe oublié ?
Créer un compte

L'inscription est gratuite et ne vous prendra que quelques instants !

Je m'inscris !

Proposition officielle d'unions de types par l'équipe de conception du langage C#
Pour tenter de fournir des solutions à tous les cas d'utilisation en déclarant quatre catégories

Le , par Jade Emy

42PARTAGES

4  0 
L'équipe de conception du langage C# propose les unions de types (aussi appelées unions discriminées) en C#. La proposition officielle tente d'apporter des solutions à tous les cas d'utilisation en les classant en quatre catégories. En effet, il peut être impossible de satisfaire certains cas d'utilisation sans en compromettre d'autres, et s'il y a plusieurs types, il vaut mieux s'efforcer de faire en sorte qu'ils aient l'air de fonctionner de la même manière autant que possible.

Lorsque vous développez un logiciel, vous pouvez rencontrer des situations où les valeurs que vous souhaitez stocker dans une variable ne sont pas toujours du même type à chaque fois. Bien que vous ne soyez généralement pas préoccupé par le fait de stocker des chaînes de caractères et des nombres au même endroit, vous pouvez avoir besoin de stocker l'un des quelques types apparentés en fonction de ce que les données sont censées représenter à ce moment-là.

Par exemple, votre application peut avoir une définition de client et une définition de fournisseur qui ne partagent que certaines des mêmes propriétés et vous pouvez avoir besoin d'effectuer une opération similaire sur les deux d'une manière qui dépend des différences.

Typiquement, c'est là que vous pouvez choisir de distribuer ces implémentations spécialisées dans les types eux-mêmes et de les exposer par le biais de méthodes abstraites communes ou d'interfaces. Toutefois, il ne s'agit là que d'une bonne pratique lorsque ces types existent principalement pour l'objectif de l'opération ou qu'il est logique que l'opération apparaisse comme une partie intrinsèque du type. Si les types ont un objectif plus large, il n'est pas souhaitable de les polluer avec des méthodes de ce type.

L'autre solution consiste à faire en sorte que la même logique gère les deux types, et si vous faites cela, vous devrez à un moment donné déclarer un paramètre ou une variable qui peut contenir l'un ou l'autre.

Vous pourriez penser que vous pouvez encore résoudre ce problème par l'héritage, en définissant à la fois Customer et le Supplier comme des classes dans une hiérarchie avec un type de base commun comme Contact. Cependant, si vous n'êtes pas en mesure de définir une telle relation, soit parce que vous ne possédez pas la définition de ces types, soit parce que vous avez trop de situations similaires et que vous ne pouvez en résoudre qu'une seule par l'héritage, soit parce que vous choisissez de ne pas intégrer les exigences de l'opération spécifique dans la définition des données, le seul choix possible est de déclarer la variable en tant qu'objet et de la laisser être n'importe quoi.

Bien que cette solution puisse fonctionner, elle ne vous permet pas de contrôler votre code par le biais de la documentation et des commentaires. Si vous êtes courageux, vous pouvez concevoir des hiérarchies de cas spéciaux de types enveloppants à placer autour de vos valeurs, ou des types agrégés personnalisés qui agissent comme des gardiens autour de tous les types de valeurs que vous voulez éventuellement stocker dans la variable, ce qui prend du temps et est lourd, surtout si vous avez beaucoup de situations similaires mais qu'elles impliquent toutes des ensembles de types différents.

Il serait préférable que C# vous permette de déclarer un type qui vous autorise à stocker un type parmi un nombre limité d'autres types au même endroit, et qu'il fasse tout le travail de protection des variables pour vous. De nombreux autres langages font déjà cela. Ils appellent généralement ces types spéciaux des unions discriminées, des unions étiquetées, des types de somme ou des unions de types. Tous résolvent le problème de permettre à une seule variable de contenir des valeurs d'une ou plusieurs formes limitées. Il est temps que C# dispose d'une fonctionnalité qui le permette également.


Solutions : les unions de types pour C#

Vous pourriez imaginer que l'implémentation la plus appropriée pour les types d'union en C# est une hiérarchie de classes avec une base abstraite représentant l'union elle-même et tous les cas spécifiques de l'union en tant que classe dérivée, parce que cela correspond vraiment bien aux concepts déjà présents dans le langage. Cela fonctionne généralement bien lorsque vous avez un cas d'utilisation spécifique à l'esprit et que vous concevez un ensemble spécifique de classes pour résoudre ce problème spécifique. Cependant, l'implémentation des unions sous forme de hiérarchies de classes présente certains inconvénients.

  • L'un d'eux est l'impossibilité de contraindre la hiérarchie, car les langages orientés objet sont généralement ouverts à l'héritage.

    Je sais qu'il n'y a que trois sous-types possibles, mais pourquoi le compilateur me demande-t-il d'avoir une valeur par défaut dans mon expression switch ?
  • Un autre problème est l'incapacité de représenter des unions de types non apparentés qui existent en dehors d'une hiérarchie unique ou même de restreindre les valeurs à un sous-ensemble de types à l'intérieur de la même hiérarchie.

    Je souhaite que ce paramètre soit limité aux chats et aux chiens, et non à tous les animaux.
  • En raison de l'implémentation de la hiérarchie des classes, la seule façon d'inclure une valeur d'un type qui existe déjà est d'utiliser une classe qui fait partie de la hiérarchie d'union pour envelopper la valeur.

    Je dois soit saisir ces champs en tant qu'objet et faire confiance à moi-même et à mon équipe pour toujours faire ce qu'il faut, soit envelopper mes valeurs dans de nouvelles instances de classe chaque fois que je veux les stocker dans la variable.
  • Enfin, les classes en C# nécessitent une allocation pour être représentées et ne peuvent pas contenir de valeurs telles que les types ref, qui peuvent être nécessaires pour des scénarios spécifiques.

    J'aimerais pouvoir utiliser les unions dans mon pipeline graphique, mais elles provoquent trop de gen 0.


Pour ces raisons, il peut être nécessaire d'avoir plus d'un type d'union, car il peut être impossible de satisfaire certains cas d'utilisation sans en compromettre d'autres, et s'il y a plusieurs types, il vaut mieux s'efforcer de faire en sorte qu'ils aient l'air de fonctionner de la même manière autant que possible.


La proposition officielle tente d'apporter des solutions à tous les cas d'utilisation en les classant en quatre catégories :

Standard : Cas d'utilisation où l'union et ses membres peuvent être définis ensemble, parce qu'ils ont une raison prédominante d'appartenir ensemble et que vous avez l'intention d'utiliser les membres comme des classes à part entière. L'allocation n'est pas un problème car vous auriez alloué les classes de toute façon.

Spécialisé : Cas d'utilisation qui doivent éviter les allocations ou qui nécessitent l'utilisation de types spéciaux et qui sont prêts à accepter certaines limitations pour y parvenir.

Ad Hoc : Cas d'utilisation nécessitant la formation d'unions à partir de types existants, éventuellement non apparentés, et où des unions déclarées de manière similaire avec les mêmes types de membres sont interchangeables les unes avec les autres.

Personnalisé : Cas d'utilisation qui ne correspondent pas aux autres catégories.

Pour voir en détails la proposition et des exemples, vous pouvez explorer la documentation complète.

Source : "Type Unions for C#"

Et vous ?

Avez-vous déjà utilisé les unions de types dans d'autres langages, et si oui qu'en pensez-vous ?
Pensez-vous que cette proposition est crédible ou pertinente ?

Voir aussi :

C# 13 : Découvrez les dernières fonctionnalités en avant-première, dont l'amélioration de la collection params et la résolution des surcharges, ainsi que l'ajout des propriétés partielles

Annonces et mises à jour de .NET à la Microsoft Build 2024 : intégration profonde de l'IA, simplification du développement-natif avec .Net Aspire, ainsi que des améliorations des fonctionnalités C# pour C# 13

Une erreur dans cette actualité ? Signalez-nous-la !

Avatar de fred1599
Expert éminent https://www.developpez.com
Le 31/07/2024 à 17:15
Bonjour,

Citation Envoyé par Jade Emy
Avez-vous déjà utilisé les unions de types dans d'autres langages, et si oui qu'en pensez-vous ?
En Python, l'équivalent des unions de type peut être réalisé en utilisant le module typing, introduit dans la PEP 484, et plus précisément l'utilisation de Union de ce module.
Un exemple de signature de fonction pourrait être :
Code : Sélectionner tout
1
2
3
from typing import Union

def process_data(data: Union[int, str]) -> None:
La fonction est process_data qui prend un paramètre nommé data où on informe qu'il peut être de deux types différents : int ou str.

Depuis Python 3.10, une syntaxe plus simple pour les unions de type a été introduite en utilisant le symbole |.
Cette syntaxe est plus concise et rend le code plus lisible.
Voici un exemple avec cette nouvelle syntaxe :
Code : Sélectionner tout
def process_data(data: int | str) -> None:
En C#, la vérification des types est intrinsèque au compilateur. Contrairement à Python, où l'outil mypy est utilisé pour effectuer des vérifications de type statiques avant l'exécution, C# effectue ces vérifications au moment de la compilation. Cela signifie que si les types ne correspondent pas, le code ne se compilera pas et une erreur sera générée par le compilateur. En python, sans mypy (d'autres outils existent), les vérifications de types ne sont qu'une information et totalement transparentes lors de l'exécution.
1  0