C # vs Java Enum (pour ceux qui découvrent C #)

182

Je programme en Java depuis un moment et je viens de me lancer sur un projet entièrement écrit en C #. J'essaie de me mettre à niveau en C #, et j'ai remarqué que les énumérations étaient utilisées à plusieurs endroits dans mon nouveau projet, mais à première vue, les énumérations de C # semblent être plus simplistes que l'implémentation Java 1.5+. Quelqu'un peut-il énumérer les différences entre les énumérations C # et Java, et comment surmonter les différences? (Je ne veux pas lancer une guerre des flammes du langage, je veux juste savoir comment faire certaines choses en C # que j'avais l'habitude de faire en Java). Par exemple, quelqu'un pourrait-il publier un équivalent C # du célèbre exemple d'énumération Planet de Sun?

public enum Planet {
  MERCURY (3.303e+23, 2.4397e6),
  VENUS   (4.869e+24, 6.0518e6),
  EARTH   (5.976e+24, 6.37814e6),
  MARS    (6.421e+23, 3.3972e6),
  JUPITER (1.9e+27,   7.1492e7),
  SATURN  (5.688e+26, 6.0268e7),
  URANUS  (8.686e+25, 2.5559e7),
  NEPTUNE (1.024e+26, 2.4746e7),
  PLUTO   (1.27e+22,  1.137e6);

  private final double mass;   // in kilograms
  private final double radius; // in meters
  Planet(double mass, double radius) {
      this.mass = mass;
      this.radius = radius;
  }
  public double mass()   { return mass; }
  public double radius() { return radius; }

  // universal gravitational constant  (m3 kg-1 s-2)
  public static final double G = 6.67300E-11;

  public double surfaceGravity() {
      return G * mass / (radius * radius);
  }
  public double surfaceWeight(double otherMass) {
      return otherMass * surfaceGravity();
  }
}

// Example usage (slight modification of Sun's example):
public static void main(String[] args) {
    Planet pEarth = Planet.EARTH;
    double earthRadius = pEarth.radius(); // Just threw it in to show usage

    // Argument passed in is earth Weight.  Calculate weight on each planet:
    double earthWeight = Double.parseDouble(args[0]);
    double mass = earthWeight/pEarth.surfaceGravity();
    for (Planet p : Planet.values())
       System.out.printf("Your weight on %s is %f%n",
                         p, p.surfaceWeight(mass));
}

// Example output:
$ java Planet 175
Your weight on MERCURY is 66.107583
Your weight on VENUS is 158.374842
[etc ...]
Ogre Psaume33
la source
1
@ycomp Je ne peux pas m'en attribuer le mérite. Il vient de Sun (maintenant Oracle): docs.oracle.com/javase/tutorial/java/javaOO/enum.html
Ogre Psalm33

Réponses:

210

Les énumérations dans le CLR sont simplement nommées constantes. Le type sous-jacent doit être intégral. En Java, une énumération ressemble plus à une instance nommée d'un type. Ce type peut être assez complexe et - comme le montre votre exemple - contenir plusieurs champs de différents types.

Pour porter l'exemple en C #, je changerais simplement l'énumération en une classe immuable et exposerais des instances statiques en lecture seule de cette classe:

using System;
using System.Collections.Generic;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Planet planetEarth = Planet.MERCURY;

            double earthRadius = pEarth.Radius; // Just threw it in to show usage
            double earthWeight = double.Parse("123");
            double earthMass   = earthWeight / pEarth.SurfaceGravity();

            foreach (Planet p in Planet.Values)
                Console.WriteLine($"Your weight on {p} is {p.SurfaceWeight(mass)}");

            Console.ReadKey();
        }
    }

    public class Planet
    {
        public static readonly Planet MERCURY = new Planet("Mercury", 3.303e+23, 2.4397e6);
        public static readonly Planet VENUS   = new Planet("Venus", 4.869e+24, 6.0518e6);
        public static readonly Planet EARTH   = new Planet("Earth", 5.976e+24, 6.37814e6);
        public static readonly Planet MARS    = new Planet("Mars", 6.421e+23, 3.3972e6);
        public static readonly Planet JUPITER = new Planet("Jupiter", 1.9e+27, 7.1492e7);
        public static readonly Planet SATURN  = new Planet("Saturn", 5.688e+26, 6.0268e7);
        public static readonly Planet URANUS  = new Planet("Uranus", 8.686e+25, 2.5559e7);
        public static readonly Planet NEPTUNE = new Planet("Neptune", 1.024e+26, 2.4746e7);
        public static readonly Planet PLUTO   = new Planet("Pluto", 1.27e+22, 1.137e6);

        public static IEnumerable<Planet> Values
        {
            get
            {
                yield return MERCURY;
                yield return VENUS;
                yield return EARTH;
                yield return MARS;
                yield return JUPITER;
                yield return SATURN;
                yield return URANUS;
                yield return NEPTUNE;
                yield return PLUTO;
            }
        }

        public string Name   { get; private set; }
        public double Mass   { get; private set; }
        public double Radius { get; private set; }

        Planet(string name, double mass, double radius) => 
            (Name, Mass, Radius) = (name, mass, radius);

        // Wniversal gravitational constant  (m3 kg-1 s-2)
        public const double G = 6.67300E-11;
        public double SurfaceGravity()            => G * mass / (radius * radius);
        public double SurfaceWeight(double other) => other * SurfaceGravity();
        public override string ToString()         => name;
    }
}
Kent Boogaart
la source
4
C'est ce genre d'énumération de type sûr que nous, les pauvres obligés d'utiliser Java 1.4 et les versions antérieures, devons implémenter ... Les énumérations de Java 5 sont peut-être la meilleure fonctionnalité de Java 5+, d'autant plus qu'elles peuvent être utilisées dans des instructions switch.
MetroidFan2002
9
@Chris: seules les énumérations d'indicateurs doivent être mises au pluriel. Autrement dit, les énumérations dont les membres sont combinés à l'aide du | opérateur.
Kent Boogaart
5
@Mladen: Cela dépend entièrement du contexte. Une énumération de planètes peut être parfaitement adaptée à un jeu qui donne accès à un nombre limité de planètes. Les modifications apportées au code peuvent être précisément ce que vous souhaitez si une nouvelle planète est ajoutée au jeu.
Kent Boogaart
3
@Richie_W vous pouvez parcourir les énumérations à l'aide de la propriété Values.
Jonathan
23
Wow ... C'est presque incroyable de voir quelque chose d'implémenté de manière plus verbeuse en C # qu'en Java
Sune Rasmussen
218

En C #, vous pouvez définir des méthodes d'extension sur les énumérations, ce qui compense certaines des fonctionnalités manquantes.

Vous pouvez définir Planetcomme une énumération et également avoir des méthodes d'extension équivalentes à surfaceGravity()et surfaceWeight().

J'ai utilisé des attributs personnalisés comme suggéré par Mikhail , mais la même chose pourrait être obtenue en utilisant un dictionnaire.

using System;
using System.Reflection;

class PlanetAttr: Attribute
{
    internal PlanetAttr(double mass, double radius)
    {
        this.Mass = mass;
        this.Radius = radius;
    }
    public double Mass { get; private set; }
    public double Radius { get; private set; }
}

public static class Planets
{
    public static double GetSurfaceGravity(this Planet p)
    {
        PlanetAttr attr = GetAttr(p);
        return G * attr.Mass / (attr.Radius * attr.Radius);
    }

    public static double GetSurfaceWeight(this Planet p, double otherMass)
    {
        return otherMass * p.GetSurfaceGravity();
    }

    public const double G = 6.67300E-11;

    private static PlanetAttr GetAttr(Planet p)
    {
        return (PlanetAttr)Attribute.GetCustomAttribute(ForValue(p), typeof(PlanetAttr));
    }

    private static MemberInfo ForValue(Planet p)
    {
        return typeof(Planet).GetField(Enum.GetName(typeof(Planet), p));
    }

}

public enum Planet
{
    [PlanetAttr(3.303e+23, 2.4397e6)]  MERCURY,
    [PlanetAttr(4.869e+24, 6.0518e6)]  VENUS,
    [PlanetAttr(5.976e+24, 6.37814e6)] EARTH,
    [PlanetAttr(6.421e+23, 3.3972e6)]  MARS,
    [PlanetAttr(1.9e+27,   7.1492e7)]  JUPITER,
    [PlanetAttr(5.688e+26, 6.0268e7)]  SATURN,
    [PlanetAttr(8.686e+25, 2.5559e7)]  URANUS,
    [PlanetAttr(1.024e+26, 2.4746e7)]  NEPTUNE,
    [PlanetAttr(1.27e+22,  1.137e6)]   PLUTO
}
finnw
la source
20
Je pense que cela devrait être voté davantage. C'est plus proche du fonctionnement des énumérations en Java. Je peux faire quelque chose comme Planet.MERCURY.GetSurfaceGravity () <- Notez la méthode d'extension sur un Enum!
thenonhacker
2
Définitivement oui. Les méthodes d'extension sur Enums (diable, les méthodes d'extension en général) sont un excellent ajout à C #.
KeithS
3
@AllonGuralnek Merci. Cependant, tout le monde ne serait pas d'accord sur les métadonnées. Voir le commentaire de MattDavey sur une question connexe codereview.stackexchange .
fin du
@finnw: Je n'ai jamais entendu parler du site Code Review SE - merci pour ça! J'ai continué cette discussion là-bas (bien que cela puisse mériter sa propre question ici sur les programmeurs).
Allon Guralnek
c'est une excellente solution - quelqu'un a-t-il testé ses performances? Par exemple, combien de temps faut-il pour accéder à l'attribut, par rapport à l'accès à une propriété d'une classe.
Simon Meyer le
35

En C #, les attributs peuvent être utilisés avec des énumérations. Un bon exemple de ce modèle de programmation avec une description détaillée est ici (Codeproject)

public enum Planet
{
   [PlanetAttr(3.303e+23, 2.4397e6)]
   Mercury,
   [PlanetAttr(4.869e+24, 6.0518e6)]
   Venus
} 

Edit: cette question a été récemment posée à nouveau et répondue par Jon Skeet: Quel est l'équivalent de l'énumération de Java en C #? Classes internes privées en C # - pourquoi ne sont-elles pas utilisées plus souvent?

Edit 2: voyez la réponse acceptée qui prolonge cette approche de manière très brillante!

Mikhail
la source
1
Agréable! Cela ne semble que légèrement maladroit, mais c'est par ailleurs une méthode très acceptable pour ajouter des données supplémentaires à une énumération. Je suis franchement étonné qu'il ait fallu autant de temps à quelqu'un pour mentionner cette excellente solution!
Ogre Psalm33
13

Les énumérations Java sont en fait des classes complètes qui peuvent avoir un constructeur privé et des méthodes, etc., tandis que les énumérations C # ne sont que des entiers nommés. L'implémentation de IMO Java est de loin supérieure.

Cette page devrait vous aider beaucoup tout en apprenant le c # provenant d'un camp java. (Le lien pointe vers les différences concernant les énumérations (faites défiler vers le haut / bas pour d'autres choses)

Richard Walton
la source
1
Bien que votre lien donne un aperçu intéressant et complet des similitudes et des différences entre C # et Java, il y a beaucoup d'erreurs dans le texte (par exemple, indique à tort que Java protected égale C # internal alors qu'il devrait être interne). Alors ne prenez pas tout pour acquis :)
mafu
1
Je ne dirais pas que les énumérations Java sont supérieures même si je suis fan de Java. C # prend en charge la déclaration d'entiers facile, comme celle FOO = 0qui est plus facile à utiliser dans les outils ORM (aucune ordinal()utilisation sujette aux erreurs n'est nécessaire). De plus, C # prend en charge les énumérations au niveau du bit qui sont souvent très utiles, en particulier en combinaison avec EntityFramework. Java devrait étendre leurs énumérations pour leur permettre d'être également liés à des entiers. Alors ils seraient supérieurs :)
djmj
4

Quelque chose comme ça je pense:

public class Planets 
{
    public static readonly Planet MERCURY = new Planet(3.303e+23, 2.4397e6);
    public static readonly Planet VENUS = new Planet(4.869e+24, 6.0518e6);
    public static readonly Planet EARTH = new Planet(5.976e+24, 6.37814e6);
    public static readonly Planet MARS = new Planet(6.421e+23, 3.3972e6);
    public static readonly Planet JUPITER = new Planet(1.9e+27,   7.1492e7);
    public static readonly Planet SATURN = new Planet(5.688e+26, 6.0268e7);
    public static readonly Planet URANUS = new Planet(8.686e+25, 2.5559e7);
    public static readonly Planet NEPTUNE = new Planet(1.024e+26, 2.4746e7);
    public static readonly Planet PLUTO = new Planet(1.27e+22,  1.137e6);
}

public class Planet
{
    public double Mass {get;private set;}
    public double Radius {get;private set;}

    Planet(double mass, double radius)
    {
        Mass = mass;
        Radius = radius;
    }

    // universal gravitational constant  (m3 kg-1 s-2)
    private static readonly double G = 6.67300E-11;

    public double SurfaceGravity()
    {
        return G * Mass / (Radius * Radius);
    }

    public double SurfaceWeight(double otherMass)
    {
        return otherMass * SurfaceGravity();
    }
}

Ou combinez les constantes dans la Planetclasse comme ci-dessus

Chris S
la source
8
Pas tout à fait - le constructeur Planet devrait être privé; une partie du point des énumérations est qu'ils sont un ensemble fixe de valeurs. Les valeurs seraient alors également définies dans la classe Planet.
Jon Skeet
Pas encore. 1) l'énumérateur est manquant :) 2) les énumérations ne devraient jamais être mutables. Oh et enfin, votre code demande une seule classe (surtout lorsque vous avez un constructeur privé)
nawfal
3

Voici une autre idée intéressante qui répond au comportement personnalisé disponible en Java. J'ai proposé la Enumerationclasse de base suivante :

public abstract class Enumeration<T>
    where T : Enumeration<T>
{   
    protected static int nextOrdinal = 0;

    protected static readonly Dictionary<int, Enumeration<T>> byOrdinal = new Dictionary<int, Enumeration<T>>();
    protected static readonly Dictionary<string, Enumeration<T>> byName = new Dictionary<string, Enumeration<T>>();

    protected readonly string name;
    protected readonly int ordinal;

    protected Enumeration(string name)
        : this (name, nextOrdinal)
    {
    }

    protected Enumeration(string name, int ordinal)
    {
        this.name = name;
        this.ordinal = ordinal;
        nextOrdinal = ordinal + 1;
        byOrdinal.Add(ordinal, this);
        byName.Add(name, this);
    }

    public override string ToString()
    {
        return name;
    }

    public string Name 
    {
        get { return name; }
    }

    public static explicit operator int(Enumeration<T> obj)
    {
        return obj.ordinal;
    }

    public int Ordinal
    {
        get { return ordinal; }
    }
}

Il a un paramètre de type simplement pour que le nombre ordinal fonctionne correctement dans différentes énumérations dérivées. L' Operatorexemple de Jon Skeet tiré de sa réponse à une autre question (http://stackoverflow.com/questions/1376312/whats-the-equivalent-of-javas-enum-in-c) ci-dessus devient alors:

public class Operator : Enumeration<Operator>
{
    public static readonly Operator Plus = new Operator("Plus", (x, y) => x + y);
    public static readonly Operator Minus =  new Operator("Minus", (x, y) => x - y);
    public static readonly Operator Times =  new Operator("Times", (x, y) => x * y);
    public static readonly Operator Divide = new Operator("Divide", (x, y) => x / y);

    private readonly Func<int, int, int> op;

    // Prevent other top-level types from instantiating
    private Operator(string name, Func<int, int, int> op)
        :base (name)
    {
        this.op = op;
    }

    public int Execute(int left, int right)
    {
        return op(left, right);
    }
}

Cela donne quelques avantages.

  • Support ordinale
  • Conversion en stringetint qui rend les instructions switch faisables
  • GetType () donnera le même résultat pour chacune des valeurs d'un type Enumeration dérivé.
  • Les méthodes Static from System.Enumpeuvent être ajoutées à la classe Enumeration de base pour permettre la même fonctionnalité.
Andrew Cooper
la source
3

nous venons de faire une extension enum pour c # https://github.com/simonmau/enum_ext

C'est juste une implémentation pour le typesafeenum, mais cela fonctionne très bien, nous avons donc créé un package à partager - amusez-vous avec

public sealed class Weekday : TypeSafeNameEnum<Weekday, int>
{
    public static readonly Weekday Monday = new Weekday(1, "--Monday--");
    public static readonly Weekday Tuesday = new Weekday(2, "--Tuesday--");
    public static readonly Weekday Wednesday = new Weekday(3, "--Wednesday--");
    ....

    private Weekday(int id, string name) : base(id, name)
    {
    }
}
Simonmau
la source
2

Une énumération Java est un sucre syntaxique permettant de présenter des énumérations de manière OO. Ce sont des classes abstraites étendant la classe Enum en Java, et chaque valeur enum est comme une implémentation d'instance publique finale statique de la classe enum. Regardez les classes générées, et pour une énumération "Foo" avec 10 valeurs, vous verrez "Foo $ 1" à "Foo $ 10" classes générées.

Cependant, je ne connais pas C #, je ne peux que spéculer qu'une énumération dans ce langage ressemble plus à une énumération traditionnelle dans les langages de style C. Je vois à partir d'une recherche rapide sur Google qu'ils peuvent contenir plusieurs valeurs, ils sont donc probablement implémentés de la même manière, mais avec beaucoup plus de restrictions que ce que le compilateur Java permet.

JeeBee
la source
3
Eh bien, tout en Java et C # n'est-il pas uniquement une question de sucre syntaxique pour les bytecodes JVM ou CLR? :) Just sayin '
thenonhacker
2

Les énumérations Java permettent des conversions de type sécurisées faciles à partir du nom en utilisant la méthode valueOf générée par le compilateur, ie

// Java Enum has generics smarts and allows this
Planet p = Planet.valueOf("MERCURY");

L'équivalent d'une énumération brute en C # est plus détaillé:

// C# enum - bit of hoop jumping required
Planet p = (Planet)Enum.Parse(typeof(Planet), "MERCURY");

Cependant, si vous suivez la route suggérée par Kent, vous pouvez facilement implémenter une ValueOfméthode dans votre classe enum.

serg10
la source
L'exemple Java utilise une méthode synthétique générée par le compilateur - rien à voir avec les génériques du tout. Enum a une méthode valueOf générique, mais qui utilise les génériques de la classe et non ceux de Enum.
Tom Hawtin - tackline
2

Je soupçonne que les énumérations en C # ne sont que des constantes internes au CLR, mais pas très familières avec elles. J'ai décompilé certaines classes en Java et je peux dire que vous voulez que les Enums soient une fois convertis.

Java fait quelque chose de sournois. Il traite la classe enum comme une classe normale avec, aussi proche que possible, en utilisant de nombreuses macros lors du référencement des valeurs enum. Si vous avez une instruction case dans une classe Java qui utilise des énumérations, elle remplace les références enum aux entiers. Si vous avez besoin d'accéder à string, il crée un tableau de chaînes indexées par un ordinal qu'il utilise dans chaque classe. Je soupçonne d'économiser sur la boxe.

Si vous téléchargez ce décompilateur, vous verrez comment il crée sa classe et l'intègre. Plutôt fascinant pour être honnête. J'avais l'habitude de ne pas utiliser la classe enum parce que je pensais que c'était trop gonflé pour juste un tableau de constantes. Je l'aime mieux que la manière limitée dont vous pouvez les utiliser en C #.

http://members.fortunecity.com/neshkov/dj.html - décompilateur Java

Paul Bruner
la source
0

L'énumération en Java est beaucoup plus complexe que l'énumération C # et donc plus puissante. Puisqu'il s'agit simplement d'un autre sucre syntaxique au moment de la compilation, je me demande s'il valait vraiment la peine d'inclure le langage étant donné son utilisation limitée dans les applications réelles. Parfois, il est plus difficile de garder des choses hors de la langue que de céder à la pression d'inclure une fonctionnalité mineure.

dmihailescu
la source
2
Je suis respectueusement en désaccord. Les énumérations Java 1.5 sont une fonctionnalité de langage puissante que j'ai utilisée à plusieurs reprises pour implémenter une solution plus centrée sur OO à un problème traitant d'un ensemble discret d'éléments nommés constants.
Ogre Psalm33
1
Peut-être que vous l'avez fait. Mais au-delà de l'intégration du langage intelligent «switch», le reste des fonctionnalités peut être facilement répliqué en C # ou Java lui-même, comme le montrent les exemples ci-dessus.
dmihailescu
@dmihailescu "Alors enum en Java est beaucoup plus complexe que C #. Alors j'ai laissé tomber Java ..."
Mukus
0
//Review the sample enum below for a template on how to implement a JavaEnum.
//There is also an EnumSet implementation below.

public abstract class JavaEnum : IComparable {
    public static IEnumerable<JavaEnum> Values {
        get {
            throw new NotImplementedException("Enumeration missing");
        }
    }

    public readonly string Name;

    public JavaEnum(string name) {
        this.Name = name;
    }

    public override string ToString() {
        return base.ToString() + "." + Name.ToUpper();
    }

    public int CompareTo(object obj) {
        if(obj is JavaEnum) {
            return string.Compare(this.Name, ((JavaEnum)obj).Name);
        } else {
            throw new ArgumentException();
        }
    }


    //Dictionary values are of type SortedSet<T>
    private static Dictionary<Type, object> enumDictionary;
    public static SortedSet<T> RetrieveEnumValues<T>() where T : JavaEnum {
        if(enumDictionary == null) {
            enumDictionary = new Dictionary<Type, object>();
        }
        object enums;
        if(!enumDictionary.TryGetValue(typeof(T), out enums)) {
            enums = new SortedSet<T>();
            FieldInfo[] myFieldInfo = typeof(T).GetFields(BindingFlags.Static | BindingFlags.DeclaredOnly | BindingFlags.Public);
            foreach(FieldInfo f in myFieldInfo) {
                if(f.FieldType == typeof(T)) {
                    ((SortedSet<T>)enums).Add((T)f.GetValue(null));
                }
            }
            enumDictionary.Add(typeof(T), enums);
        }
        return (SortedSet<T>)enums;
    }
}


//Sample JavaEnum
public class SampleEnum : JavaEnum {
    //Enum values
    public static readonly SampleEnum A = new SampleEnum("A", 1);
    public static readonly SampleEnum B = new SampleEnum("B", 2);
    public static readonly SampleEnum C = new SampleEnum("C", 3);

    //Variables or Properties common to all enums of this type
    public int int1;
    public static int int2 = 4;
    public static readonly int int3 = 9;

    //The Values property must be replaced with a call to JavaEnum.generateEnumValues<MyEnumType>() to generate an IEnumerable set.
    public static new IEnumerable<SampleEnum> Values {
        get {
            foreach(var e in JavaEnum.RetrieveEnumValues<SampleEnum>()) {
                yield return e;
            }
            //If this enum should compose several enums, add them here
            //foreach(var e in ChildSampleEnum.Values) {
            //    yield return e;
            //}
        }
    }

    public SampleEnum(string name, int int1)
        : base(name) {
        this.int1 = int1;
    }
}


public class EnumSet<T> : SortedSet<T> where T : JavaEnum {
    // Creates an enum set containing all of the elements in the specified element type.
    public static EnumSet<T> AllOf(IEnumerable<T> values) {
        EnumSet<T> returnSet = new EnumSet<T>();
        foreach(T item in values) {
            returnSet.Add(item);
        }
        return returnSet;
    }

    // Creates an enum set with the same element type as the specified enum set, initially containing all the elements of this type that are not contained in the specified set.
    public static EnumSet<T> ComplementOf(IEnumerable<T> values, EnumSet<T> set) {
        EnumSet<T> returnSet = new EnumSet<T>();
        foreach(T item in values) {
            if(!set.Contains(item)) {
                returnSet.Add(item);
            }
        }
        return returnSet;
    }

    // Creates an enum set initially containing all of the elements in the range defined by the two specified endpoints.
    public static EnumSet<T> Range(IEnumerable<T> values, T from, T to) {
        EnumSet<T> returnSet = new EnumSet<T>();
        if(from == to) {
            returnSet.Add(from);
            return returnSet;
        }
        bool isFrom = false;
        foreach(T item in values) {
            if(isFrom) {
                returnSet.Add(item);
                if(item == to) {
                    return returnSet;
                }
            } else if(item == from) {
                isFrom = true;
                returnSet.Add(item);
            }
        }
        throw new ArgumentException();
    }

    // Creates an enum set initially containing the specified element(s).
    public static EnumSet<T> Of(params T[] setItems) {
        EnumSet<T> returnSet = new EnumSet<T>();
        foreach(T item in setItems) {
            returnSet.Add(item);
        }
        return returnSet;
    }

    // Creates an empty enum set with the specified element type.
    public static EnumSet<T> NoneOf() {
        return new EnumSet<T>();
    }

    // Returns a copy of the set passed in.
    public static EnumSet<T> CopyOf(EnumSet<T> set) {
        EnumSet<T> returnSet = new EnumSet<T>();
        returnSet.Add(set);
        return returnSet;
    }

    // Adds a set to an existing set.
    public void Add(EnumSet<T> enumSet) {
        foreach(T item in enumSet) {
            this.Add(item);
        }
    }

    // Removes a set from an existing set.
    public void Remove(EnumSet<T> enumSet) {
        foreach(T item in enumSet) {
            this.Remove(item);
        }
    }
}
Jim
la source
0

Vous pouvez également utiliser une classe utilitaire pour chaque type d'énumération qui contient une instance avec des données avancées pour chaque valeur d'énumération.

public enum Planet
{
    MERCURY,
    VENUS
}

public class PlanetUtil
{
    private static readonly IDictionary<Planet, PlanetUtil> PLANETS = new Dictionary<Planet, PlanetUtil();

    static PlanetUtil()
    {
        PlanetUtil.PLANETS.Add(Planet.MERCURY, new PlanetUtil(3.303e+23, 2.4397e6));
        PlanetUtil.PLANETS.Add(Planet.VENUS, new PlanetUtil(4.869e+24, 6.0518e6));
    }

    public static PlanetUtil GetUtil(Planet planet)
    {
        return PlanetUtil.PLANETS[planet];
    }

    private readonly double radius;
    private readonly double mass;

    public PlanetUtil(double radius, double mass)
    {
        this.radius = radius;
        this.mass = mass;
    }

    // getter
}
djmj
la source