Tengo una enumeración en un espacio de nombres de bajo nivel. Me gustaría proporcionar una clase o enumeración en un espacio de nombres de nivel medio que "herede" la enumeración de bajo nivel.
namespace low
{
public enum base
{
x, y, z
}
}
namespace mid
{
public enum consume : low.base
{
}
}
Espero que esto sea posible, o tal vez algún tipo de clase que pueda ocupar el lugar del consumo de enumeración que proporcionará una capa de abstracción para la enumeración, pero aún así permitirá que una instancia de esa clase acceda a la enumeración.
Pensamientos?
EDITAR: Una de las razones por las que no acabo de cambiar esto a consts en clases es que un servicio que debo consumir necesita la enumeración de bajo nivel. Me dieron los WSDL y los XSD, que definen la estructura como una enumeración. El servicio no se puede cambiar.
Respuestas:
Esto no es posible. Las enumeraciones no pueden heredar de otras enumeraciones. De hecho, todas las enumeraciones deben heredar de
System.Enum
. C # permite que la sintaxis cambie la representación subyacente de los valores de enumeración que parece herencia, pero en realidad todavía heredan de System.enum.Consulte la sección 8.5.2 de la especificación de la CLI para obtener todos los detalles. Información relevante de la especificación
System.Enum
fuente
switch
situación.Puedes lograr lo que quieres con las clases:
Ahora puede usar estas clases de forma similar a cuando eran enumeraciones:
Actualización (después de su actualización de la pregunta):
Si asigna los mismos valores int a las constantes como se define en la enumeración existente, puede convertir entre la enumeración y las constantes, por ejemplo:
fuente
Enum.GetValues(typeof(MyEnum)
void Test() { foreach (System.Reflection.PropertyInfo pi in typeof(Consume).GetProperties()) { Console.WriteLine(pi.Name); } }
La respuesta corta es no. Puedes jugar un poco, si quieres:
Siempre puedes hacer algo como esto:
Pero, no funciona tan bien porque Base.A! = Consume.A
Sin embargo, siempre puedes hacer algo como esto:
Para cruzar entre Base y Consumir ...
También podría convertir los valores de las enumeraciones como ints, y compararlos como ints en lugar de enum, pero ese tipo de apesta también.
El método de extensión return debería escribir cast it type T.
fuente
Base.A == (Base)Consume.A
int
tendría mucho más sentido. ¿Cuándo una enumeración tendría una parte fraccionaria?Las soluciones anteriores que usan clases con constantes int carecen de seguridad de tipo. Es decir, podría inventar nuevos valores realmente no definidos en la clase. Además, no es posible, por ejemplo, escribir un método tomando una de estas clases como entrada.
Necesitarías escribir
Sin embargo, existe una solución basada en clases de los viejos tiempos de Java, cuando no había enumeraciones disponibles. Esto proporciona un comportamiento casi enum. La única advertencia es que estas constantes no se pueden usar dentro de una instrucción switch.
fuente
object
's haría que los valores sean diferentes para cada instancia del ensamblado, por lo que no se pueden serializar.Ignorando el hecho de que base es una palabra reservada, no se puede hacer la herencia de enum.
Lo mejor que puedes hacer es algo así:
Dado que todos son del mismo tipo base (es decir, int), puede asignar el valor de una instancia de un tipo a otro, que es una conversión. No es ideal pero funciona.
fuente
Sé que esta respuesta es un poco tarde, pero esto es lo que terminé haciendo:
Entonces puedo hacer cosas como:
fuente
Esto es lo que hice. Lo que he hecho de manera diferente es usar el mismo nombre y la
new
palabra clave en el "consumidor"enum
. Dado que el nombre delenum
mismo es el mismo, puede usarlo sin pensarlo y será correcto. Además, obtienes inteligencia. Solo debe tener cuidado manualmente al configurar que los valores se copien de la base y mantenerlos sincronizados. Puede ayudarlo junto con los comentarios de código. Esta es otra razón por la cual en la base de datos al almacenarenum
valores siempre almaceno la cadena, no el valor. Porque si está utilizando valores enteros crecientes asignados automáticamente, estos pueden cambiar con el tiempo.fuente
SmallMedium = 100,
), de modo que pueda mantener la compatibilidad con versiones anteriores de su software cuando agregue nuevos valores en la clase base. Por ejemplo, agregar unHuge
tamaño en su enumeración base se asignaría4
a su valor, pero4
ya estáSmallMedium
en la clase derivada.Huge
en la clase base necesitaría unHuge
en la subclase antesSmallMedium
BaseBall
puede no ser el nombre más inteligente aquí. Es confuso. Dado que una pelota de béisbol es realmente una cosa. Si te pierdes que esto es solo una clase base para la pelota, parece muy extraño que un voleibol herede de una pelota de béisbol físicamente más pequeña :). Mi sugerencia es simplemente usarBall
Solución alternativa
En mi empresa, evitamos "saltar sobre proyectos" para llegar a proyectos de nivel inferior no comunes. Por ejemplo, nuestra capa de presentación / API solo puede hacer referencia a nuestra capa de dominio, y la capa de dominio solo puede hacer referencia a la capa de datos.
Sin embargo, este es un problema cuando hay enumeraciones que deben ser referenciadas tanto por la presentación como por las capas de dominio.
Aquí está la solución que hemos implementado (hasta ahora). Es una solución bastante buena y funciona bien para nosotros. Las otras respuestas estaban llegando a todo esto.
La premisa básica es que las enumeraciones no se pueden heredar, pero las clases sí. Entonces...
Luego, para "heredar" las enumeraciones en otro proyecto de nivel superior ...
Esto tiene tres ventajas reales ...
Para hacer referencia a las enumeraciones en el primer proyecto , puede usar el prefijo de la clase: BaseEnums.StatusType.Pending o agregar un "uso de BaseEnums estáticos"; declaración a sus usos.
Sin embargo, en el segundo proyecto al tratar con la clase heredada, no pude obtener el "uso de static ..." enfoque funcionara, por lo que todas las referencias a las "enumeraciones heredadas" irían precedidas de la clase, por ejemplo, SubEnums.StatusType.Pending . Si a alguien se le ocurre una forma de permitir que se use el enfoque de "usar estática" en el segundo proyecto, avíseme.
Estoy seguro de que esto se puede ajustar para hacerlo aún mejor, pero esto realmente funciona y he usado este enfoque en proyectos de trabajo.
Por favor vote esto si lo encuentra útil.
fuente
También quería sobrecargar Enums y creé una mezcla de la respuesta de 'Seven' en esta página y la respuesta de 'Merlyn Morgan-Graham' en una publicación duplicada de esto , más un par de mejoras.
Principales ventajas de mi solución sobre las demás:
Esta es una solución lista para usar y se puede insertar directamente en su proyecto. Está diseñado para mis necesidades, por lo que si no le gustan algunas partes, simplemente reemplácelas con su propio código.
Primero, está la clase base de la
CEnum
que todas las enumeraciones personalizadas deberían heredar. Tiene la funcionalidad básica, similar alEnum
tipo .net :En segundo lugar, aquí hay 2 clases Enum derivadas. Todas las clases derivadas necesitan algunos métodos básicos para funcionar como se espera. Siempre es el mismo código repetitivo; Todavía no he encontrado una manera de externalizarlo a la clase base. El código del primer nivel de herencia difiere ligeramente de todos los niveles posteriores.
Las clases se han probado con éxito con el siguiente código:
fuente
Las enumeraciones no son clases reales, incluso si lo parecen. Internamente, se tratan como su tipo subyacente (por defecto Int32). Por lo tanto, solo puede hacer esto "copiando" valores individuales de una enumeración a otra y convirtiéndolos en su número entero para compararlos para la igualdad.
fuente
Las enumeraciones no pueden derivarse de otras enumeraciones, sino solo de int, uint, short, ushort, long, ulong, byte y sbyte.
Como dijo Pascal, puede usar los valores o constantes de otra enumeración para inicializar un valor de enumeración, pero eso es todo.
fuente
Otra posible solución:
HTH
fuente
Esto no es posible (como ya mencionó @JaredPar). Tratar de poner la lógica para solucionar esto es una mala práctica. En caso de que tenga un
base class
que tenga unenum
, debe enumerar todos los posiblesenum-values
allí, y la implementación de la clase debería funcionar con los valores que conoce.Por ejemplo, supongamos que tiene una clase base
BaseCatalog
y tiene unenum ProductFormats
(Digital
,Physical
). Entonces puede tener unMusicCatalog
oBookCatalog
que podría contener ambosDigital
yPhysical
productos, pero si la clase esClothingCatalog
, solo debería contenerPhysical
productos.fuente
Me doy cuenta de que llego un poco tarde a esta fiesta, pero aquí están mis dos centavos.
Todos tenemos claro que la herencia de Enum no es compatible con el marco. Se han sugerido algunas soluciones muy interesantes en este hilo, pero ninguna de ellas se sentía exactamente como lo que estaba buscando, así que tuve que intentarlo yo mismo.
Presentación: ObjectEnum
Puede consultar el código y la documentación aquí: https://github.com/dimi3tron/ObjectEnum .
Y el paquete aquí: https://www.nuget.org/packages/ObjectEnum
O simplemente instalarlo:
Install-Package ObjectEnum
En resumen,
ObjectEnum<TEnum>
actúa como una envoltura para cualquier enumeración. Al anular GetDefinedValues () en las subclases, se puede especificar qué valores de enumeración son válidos para esta clase específica.Se han agregado varias sobrecargas de operadores para que una
ObjectEnum<TEnum>
instancia se comporte como si fuera una instancia de la enumeración subyacente, teniendo en cuenta las restricciones de valor definidas. Esto significa que puede comparar fácilmente la instancia con un valor int o enum, y así usarlo en un caso de cambio o cualquier otro condicional.Me gustaría referirme al repositorio de github mencionado anteriormente para ver ejemplos e información adicional.
Espero que encuentres esto útil. Siéntase libre de comentar o abrir un problema en github para más pensamientos o comentarios.
Aquí hay algunos ejemplos breves de lo que puede hacer con
ObjectEnum<TEnum>
:fuente
Puede realizar la herencia en enumeración, sin embargo, se limita solo a los siguientes tipos. int, uint, byte, sbyte, corto, ushort, largo, ulong
P.ej
fuente