Qual è l'equivalente dell'enum di Java in C#?




enums (4)

Ecco un'altra idea interessante. Ho trovato la seguente classe di base Enumeration :

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; }
    }
}

Ha un parametro di tipo praticamente solo così il conteggio ordinale funzionerà correttamente tra le diverse enumerazioni derivate. L'esempio di Jon's Operator sopra diventa quindi:

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);
    }
}

Questo offre alcuni vantaggi.

  • Supporto ordinale
  • Conversione su string e int che rende fattibili le istruzioni switch
  • GetType () darà lo stesso risultato per ciascuno dei valori di un tipo Enumeration derivato.
  • I metodi statici di System.Enum possono essere aggiunti alla classe di enumerazione di base per consentire la stessa funzionalità.

Questa domanda ha già una risposta qui:

Qual è l'equivalente dell'enum di Java in C #?


La funzionalità completa di enum di Java non è disponibile in C #. Puoi venire ragionevolmente vicino usando i tipi annidati e un costruttore privato. Per esempio:

using System;
using System.Collections.Generic;
using System.Xml.Linq;

public abstract class Operator
{
    public static readonly Operator Plus = new PlusOperator();
    public static readonly Operator Minus = 
         new GenericOperator((x, y) => x - y);
    public static readonly Operator Times = 
         new GenericOperator((x, y) => x * y);
    public static readonly Operator Divide = 
         new GenericOperator((x, y) => x / y);

    // Prevent other top-level types from instantiating
    private Operator()
    {
    }

    public abstract int Execute(int left, int right);

    private class PlusOperator : Operator
    {
        public override int Execute(int left, int right)
        {
            return left + right;
        }
    }

    private class GenericOperator : Operator
    {
        private readonly Func<int, int, int> op;

        internal GenericOperator(Func<int, int, int> op)
        {
            this.op = op;
        }

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

Ovviamente non è necessario utilizzare i tipi annidati, ma forniscono la comoda parte "comportamento personalizzato" per cui le enumerazioni Java sono utili. In altri casi puoi semplicemente passare argomenti a un costruttore privato per ottenere un ben noto insieme limitato di valori.

Alcune cose che non ti danno:

  • Supporto ordinale
  • Cambia supporto
  • EnumSet
  • Serializzazione / deserializzazione (come singleton)

Alcuni di questi potrebbero probabilmente essere fatti con abbastanza sforzo, anche se switch non sarebbe fattibile senza l'hacker. Ora, se il linguaggio ha fatto qualcosa del genere, potrebbe fare cose interessanti per far funzionare lo switch rendendo automatico lo hackery (ad esempio dichiarando automaticamente un carico di campi const , e cambiando qualsiasi passaggio sul tipo enum a uno scambio su interi, consentendo solo " noti "casi.)

Oh, e i tipi parziali significano che non devi avere tutti i valori enum nello stesso file. Se ogni valore è abbastanza coinvolto (il che è sicuramente possibile) ognuno di essi potrebbe avere il proprio file.


Probabilmente potresti usare il vecchio pattern enum typesafe che abbiamo usato in Java prima che ne avessimo di reali (presumendo che quelli in C # in realtà non siano classi come affermazioni di commento). Il modello è descritto poco prima della metà di questa pagina


enum , o hai bisogno di qualcosa in particolare che le enumerazioni di Java abbiano ma c # no?





enums