programacion lenguaje historia caracteristicas c# java enums

lenguaje - c# historia



¿Cuál es el equivalente de la enumeración de Java en C#? (6)

Aquí hay otra idea interesante. Se me ocurrió la siguiente clase base de 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; } } }

Básicamente, tiene un parámetro de tipo para que el recuento ordinal funcione correctamente en diferentes enumeraciones derivadas. El ejemplo de Operator de Jon anterior se convierte en:

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

Esto le da algunas ventajas.

  • Soporte ordinal
  • Conversión a string e int que hace factibles las instrucciones switch
  • GetType () dará el mismo resultado para cada uno de los valores de un tipo de enumeración derivado.
  • Los métodos estáticos de System.Enum se pueden agregar a la clase de enumeración base para permitir la misma funcionalidad.

Esta pregunta ya tiene una respuesta aquí:

¿Cuál es el equivalente de la enumeración de Java en C #?


La funcionalidad de enumeración completa de Java no está disponible en C #. Sin embargo, puede acercarse razonablemente usando tipos anidados y un constructor privado. Por ejemplo:

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

Por supuesto, no tiene que usar tipos anidados, pero le dan la práctica parte de "comportamiento personalizado" para la cual son agradables las enumeraciones de Java. En otros casos, simplemente puede pasar argumentos a un constructor privado para obtener un conjunto restringido de valores bien conocido.

Algunas cosas que esto no te da:

  • Soporte ordinal
  • Soporte de interruptor
  • EnumSet
  • Serialización / deserialización (como un singleton)

Algo de eso probablemente podría hacerse con suficiente esfuerzo, aunque el cambio no sería realmente posible sin la piratería. Ahora, si el lenguaje hiciera algo como esto, podría hacer cosas interesantes para hacer que el interruptor funcione de forma automática (por ejemplo, declarar automáticamente una carga de campos const y cambiar cualquier interruptor sobre el tipo de enumeración a un interruptor sobre enteros, solo permitiendo " conocidos "casos.)

Ah, y los tipos parciales significan que no es necesario tener todos los valores de enumeración en el mismo archivo. Si cada valor se involucrara bastante (lo cual es definitivamente posible), cada uno podría tener su propio archivo.


Las enumeraciones son una de las pocas características de lenguaje que se implementa mejor en java que en c #. En java, las enumeraciones son instancias con nombre completas de un tipo, mientras que las enumeraciones c # son básicamente constantes con nombre.

Dicho esto, para el caso básico, se verán similares. Sin embargo, en java, tiene más poder, ya que puede agregar comportamiento a las enumeraciones individuales, ya que son clases de pleno derecho.

¿Hay alguna característica en particular que estás buscando?


Probablemente podría usar el antiguo patrón de enumeración que utilizamos en Java antes de obtener los reales (suponiendo que los de C # realmente no sean clases como afirma un comentario). El patrón se describe justo antes de la mitad de esta página.


enum , o necesitas algo en particular que las enumeraciones de Java tienen pero c # no?


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