Question

Existe-t-il de bonnes solutions pour représenter une énumération paramétrée dans C# 3.0? Je recherche quelque chose comme OCaml ou Haxe a. Je ne peux que penser à la hiérarchie des classes avec un simple champ d’énumération pour faciliter le basculement pour le moment, peut-être y at-il de meilleures idées?

Voir l'exemple Ocaml ci-dessous dans l'une des réponses, suivi d'un code Haxe:

enum Tree {
   Node(left: Tree, right: Tree);
   Leaf(val: Int);
}
Était-ce utile?

La solution

Ne connaissant pas OCaml ou Haxe, et n'étant pas assez intelligent pour comprendre les autres explications, je suis allé voir le Documentation Haxe enum - le bit" Paramètres de type enum "en bas semble être la partie pertinente.

D'après ce que je comprends,

Une énumération "normale" est fondamentalement une valeur limitée aux choses que vous avez définies dans votre définition d’énum. Exemple C #:

enum Color{ Red, Green, Yellow, Blue };
Color c = Color.Red;

c peut être Red, Green, Yellow ou Blue, mais rien d'autre.

Dans Haxe, vous pouvez ajouter des types complexes aux énumérations, exemple élaboré à partir de leur page:

enum Cell<T>{ 
  empty; 
  cons( item : T, next : Cell<T> )
}

Cell<int> c = <I don't know>;

Ce que cela semble signifier, c’est que empty est limité à la valeur littérale cons(item, next) (comme nos anciennes énumérations C #), ou peut également être un type complexe <= >, où item est un T et next est un Cell<T>.

N'ayant jamais utilisé cela, on dirait qu'il génère probablement des types anonymes (comme le fait le compilateur C # quand vous le faites new { Name='Joe'}.
Chaque fois que vous accédez à la valeur enum, vous devez déclarer #define Red 1 et Color à ce moment-là, et il semble que les variables associées soient liées à des variables locales temporaires.

Exemple avec Haxe - Vous pouvez voir que "next" est utilisé en tant que variable locale temporaire pour extraire des données de la structure des cons anonymes:

switch( c ) {
  case empty : 0;
  case cons(item,next): 1 + cell_length(next);
}

Pour être honnête, cela m’a bouleversé la tête lorsque j’ai «cliqué» sur ce qu’il semblait faire. Cela semble incroyablement puissant, et je comprends pourquoi vous recherchez une fonctionnalité similaire en C #.

Les énumérations C # sont à peu près les mêmes que les énumérations C / ++ à partir desquelles elles ont été copiées. C'est en gros une bonne façon de dire List<ICell<T>> afin que le compilateur puisse faire des comparaisons et stocker des entiers plutôt que des chaînes lorsque vous passez EmptyCell des objets.

Ce que je voudrais faire en C # serait d'utiliser des génériques et des interfaces. Quelque chose comme ça:

public interface ICell<T> {
   T Item{ get; set; }
   ICell<T>{ get; set; }
}

class Cons<T> : ICell<T> {
  public T Item{ get; set; } /* C#3 auto-backed property */
  public Cell<T> Next{ get; set; }
}

class EmptyCell<T> : ICell<T>{
  public T Item{ get{ return default(T); set{ /* do nothing */ }; }
  public ICell<T> Next{ get{ return null }; set{ /* do nothing */; }
}

Vous pourriez alors avoir un Next qui contiendrait des éléments et la cellule suivante, et vous pourriez insérer Cons à la fin (ou simplement avoir la référence <=> explicitement définie sur null). Les avantages étant que, comme <=> ne contient aucune variable membre, il ne nécessite aucun espace de stockage (comme le <=> dans Haxe), contrairement à une <=> cellule.
Le compilateur peut également intégrer / optimiser les méthodes dans <=> car elles ne font rien, il peut donc y avoir une augmentation de la vitesse par rapport à un <=> avec ses données de membre définies sur null.

Je ne sais pas vraiment. J'apprécierais toute autre solution possible, car je ne suis pas particulièrement fier de la vôtre: -)

Autres conseils

Utilisez une classe dotée de propriétés statiques pour représenter les valeurs d'énumération. Vous pouvez éventuellement utiliser un constructeur privé pour forcer toutes les références à la classe à passer par une propriété statique.

Jetez un coup d’œil à la System.Drawing.Color classe. Il utilise cette approche.

C # (le framework .NET en général, autant que je sache) ne supporte pas les énumérations paramétrées comme le fait Java. Cela étant dit, vous voudrez peut-être examiner les attributs. Certaines des fonctionnalités dont sont capables les énumérations Java sont relativement réalisables avec les attributs.

Qu'est-ce qui ne va pas avec l'utilisation d'une classe pour cela? C’est moche, mais c’est comme ça que les Java l'ont fait jusqu'à ce qu'ils aient le support du langage intégré Enum!

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top