¿Es posible definir una conversión implícita de enumeraciones en c #?
algo que pueda lograr esto?
public enum MyEnum
{
one = 1, two = 2
}
MyEnum number = MyEnum.one;
long i = number;
¿Si no, porque no?
c#
enums
implicit-conversion
implicit
Adam Naylor
fuente
fuente
enum YesNo {Yes, No}
que podría convertirse implícitamente en bool.Respuestas:
Hay una solucion. Considera lo siguiente:
Lo anterior ofrece conversión implícita:
Esto es bastante más trabajo que declarar una enumeración normal (aunque puede refactorizar algunos de los anteriores en una clase base genérica común). Puede ir aún más lejos haciendo que la clase base implemente IComparable e IEquatable, así como agregando métodos para devolver el valor de los atributos de descripción, los nombres declarados, etc.
Escribí una clase base (RichEnum <>) para manejar la mayoría del trabajo duro, lo que facilita la declaración de enumeraciones anterior a:
La clase base (RichEnum) se enumera a continuación.
fuente
No puede realizar conversiones implícitas (excepto cero) y no puede escribir sus propios métodos de instancia; sin embargo, probablemente pueda escribir sus propios métodos de extensión:
Sin embargo, esto no te da mucho (en comparación con solo hacer un reparto explícito).
Una de las principales veces que he visto que la gente quiere esto es para hacer la
[Flags]
manipulación a través de genéricos, es decir, unbool IsFlagSet<T>(T value, T flag);
método. Desafortunadamente, C # 3.0 no es compatible con operadores de genéricos, pero puede evitar esto usando cosas como esta , que hacen que los operadores estén totalmente disponibles con genéricos.fuente
fuente
static class
, supongo. No hay ninguna ventaja en discutir ninguno de los casos en elIL
código final .Adapté la excelente clase base genérica RichEnum de Mark.
Fijación
Felicitaciones a Mark por la espléndida idea + implementación, aquí está para todos ustedes:
Una muestra de uso que ejecuté en mono:
Produciendo la salida
Nota: mono 2.6.7 requiere una conversión explícita adicional que no se requiere cuando se usa mono 2.8.2 ...
fuente
FirstOrDefault
, para evitar asumir que solo hay un único atributo). Sea o no asumir ese tipo de cosas es 'una buena idea' (o un mal uno, para el caso) es, por supuesto, depende del contextoTDerived instance = (TDerived)field.GetValue(null);
resultainstance
sernull
. Parece que el tiempo de ejecución Mono debe tener un orden de inicialización de tipo diferente al de .NET que permite que esto funcione. ¡Misterioso! En su lugar, tuve que mover ese código a un método estático y llamarlo desde el inicializador de tipo en la subclase.No puede declarar conversiones implícitas en tipos de enumeración, porque no pueden definir métodos. La palabra clave implícita de C # se compila en un método que comienza con 'op_', y en este caso no funcionaría.
fuente
Probablemente podría, pero no para la enumeración (no puede agregarle un método). Puede agregar una conversión implícita a su propia clase para permitir que una enumeración se convierta en ella,
La pregunta sería ¿por qué?
En general .Net evita (y usted también debería hacerlo) cualquier conversión implícita en la que se puedan perder datos.
fuente
Si define la base de la enumeración como larga, puede realizar una conversión explícita. No sé si puede usar conversiones implícitas ya que las enumeraciones no pueden tener métodos definidos en ellas.
Además, tenga en cuenta que una enumeración no inicializada tendrá como valor predeterminado 0 o el primer elemento, por lo que en la situación anterior probablemente sería mejor definirla
zero = 0
también.fuente
: long
aquí; la conversión explícita funcionaría bien sin ella. La única conversión implícita legal es cero.los enumeradores son en gran medida inútiles para mí debido a esto, OP.
Termino haciendo fotos todo el tiempo:
la solución simple
El problema clásico de ejemplo es el conjunto VirtualKey para detectar pulsaciones de teclas.
El problema aquí es que no puede indexar la matriz con la enumeración porque no puede convertir implícitamente la enumeración en ushort (aunque incluso basamos la enumeración en ushort)
En este contexto específico, las enumeraciones están obsoletas por la siguiente estructura de datos. . . .
fuente
He solucionado un problema con la respuesta de sehe al ejecutar el código en MS .net (no Mono). Para mí, específicamente, el problema ocurrió en .net 4.5.1, pero otras versiones también parecen afectadas.
La cuestión
acceder a una
public static TDervied MyEnumValue
por la reflexión (a través deFieldInfo.GetValue(null)
qué no initialize dicho campo.La solución
En lugar de asignar nombres a
TDerived
instancias sobre el inicializador estático,RichEnum<TValue, TDerived>
esto se hace perezosamente en el primer acceso deTDerived.Name
. El código:que, en mi caso, se basa en
EquatableBase<T>
:Nota
¡El código anterior no incorpora todas las características de la respuesta original de Mark !
Gracias
¡Gracias a Mark por proporcionar su
RichEnum
implementación y gracias a sehe por proporcionar algunas mejoras!fuente
Encontré una solución aún más fácil tomada desde aquí /codereview/7566/enum-vs-int-wrapper-struct Pegué el siguiente código desde ese enlace en caso de que no funcione en el futuro.
fuente
Creé esta utilidad para ayudarme a convertir un Enum a PrimitiveEnum y PrimitiveEnum a
byte, sbyte, short, ushort, int, uint, long, or ulong
.Entonces, esto técnicamente convierte cualquier enumeración en cualquiera de sus valores primitivos.
Ver commit en https://github.com/McKabue/McKabue.Extentions.Utility/blob/master/src/McKabue.Extentions.Utility/Enums/PrimitiveEnum.cs
fuente
uint
s para las que el juego en sí suele hacerenum
, pero el marco no sabe nada. Tener que hacerlo(uint)
al llamar al marco fue un dolor. Tu idea al revés funciona perfectamente. En lugar destruct
almacenar elEnum
, tengo unstruct IdNumber
que almacenauint
pero convierte de forma implícita elEnum
s que usa el juego. En lugar de escribir los parámetros del marco comouint
, puedo escribirlosIdNumber
, y el marco puede transmitirlos internamente de manera eficiente, incluso haciendo operaciones integrales en ellos.La introducción de conversiones implícitas para los tipos de enumeración rompería la seguridad de los tipos, por lo que no recomendaría hacerlo. ¿Por qué querrías hacer eso? El único caso de uso para esto que he visto es cuando desea poner los valores de enumeración en una estructura con un diseño predefinido. Pero incluso entonces, puede usar el tipo de enumeración en la estructura y simplemente decirle al Marshaller qué debe hacer con esto.
fuente