J'ai une énumération dans un espace de noms de bas niveau. Je voudrais fournir une classe ou une énumération dans un espace de noms de niveau intermédiaire qui «hérite» de l'énumération de bas niveau.
namespace low
{
public enum base
{
x, y, z
}
}
namespace mid
{
public enum consume : low.base
{
}
}
J'espère que cela est possible, ou peut-être une sorte de classe qui peut remplacer la consommation d'énumération qui fournira une couche d'abstraction pour l'énumération, mais laisser encore une instance de cette classe accéder à l'énumération.
Pensées?
EDIT: L'une des raisons pour lesquelles je ne viens pas de passer à consts dans les classes est que l'énumération de bas niveau est nécessaire à un service que je dois consommer. On m'a donné les WSDL et les XSD, qui définissent la structure comme une énumération. Le service ne peut pas être modifié.
Réponses:
Ce n'est pas possible. Les énumérations ne peuvent pas hériter d'autres énumérations. En fait, tous les énumérations doivent hériter de
System.Enum
. C # permet à la syntaxe de changer la représentation sous-jacente des valeurs d'énumération qui ressemble à l'héritage, mais en réalité, elles héritent toujours de System.enum.Voir la section 8.5.2 de la spécification CLI pour les détails complets. Informations pertinentes de la spécification
System.Enum
la source
switch
situation.Vous pouvez réaliser ce que vous voulez avec des cours:
Maintenant, vous pouvez utiliser ces classes de la même manière que lorsqu'elles étaient des énumérations:
Mise à jour (après votre mise à jour de la question):
Si vous affectez les mêmes valeurs int aux constantes définies dans l'énumération existante, vous pouvez effectuer un cast entre l'énumération et les constantes, par exemple:
la source
Enum.GetValues(typeof(MyEnum)
void Test() { foreach (System.Reflection.PropertyInfo pi in typeof(Consume).GetProperties()) { Console.WriteLine(pi.Name); } }
La réponse courte est non. Vous pouvez jouer un peu, si vous le souhaitez:
Vous pouvez toujours faire quelque chose comme ça:
Mais cela ne fonctionne pas très bien parce que Base.A! = Consume.A
Vous pouvez toujours faire quelque chose comme ça, cependant:
Pour croiser Base et Consommer ...
Vous pouvez également convertir les valeurs des énumérations en nombres entiers et les comparer en tant qu'ints au lieu d'énumérations, mais ce type est également nul.
Le retour de la méthode d'extension doit taper cast it type T.
la source
Base.A == (Base)Consume.A
int
aurait beaucoup plus de sens. Quand un enum aurait-il une partie fractionnaire!?!?!Les solutions ci-dessus utilisant des classes avec des constantes int manquent de sécurité de type. C'est-à-dire que vous pourriez inventer de nouvelles valeurs réellement non définies dans la classe. De plus il n'est pas possible par exemple d'écrire une méthode prenant une de ces classes en entrée.
Vous auriez besoin d'écrire
Cependant, il existe une solution basée sur les classes de l'ancien temps de Java, quand il n'y avait pas d'énumérations disponibles. Cela fournit un comportement presque énuméré. La seule mise en garde est que ces constantes ne peuvent pas être utilisées dans une instruction switch.
la source
object
rendrait les valeurs différentes pour chaque instanciation de l'assembly afin qu'elles ne puissent pas être sérialisées.Ignorant le fait que la base est un mot réservé, vous ne pouvez pas faire d'héritage d'énumération.
La meilleure chose que vous puissiez faire est quelque chose comme ça:
Comme ils sont tous du même type de base (c'est-à-dire: int), vous pouvez attribuer la valeur d'une instance d'un type à l'autre qui est castée. Pas idéal mais ça marche.
la source
Je sais que cette réponse est un peu tard mais c'est ce que j'ai fini par faire:
Ensuite, je suis capable de faire des choses comme:
la source
C'est ce que j'ai fait. Ce que j'ai fait différemment, c'est utiliser le même nom et le
new
mot - clé sur le "consommer"enum
. Étant donné que le nom duenum
est le même, vous pouvez simplement l'utiliser sans réfléchir et il aura raison. De plus, vous obtenez l'intellisense. Il vous suffit de vous assurer manuellement lors de la configuration que les valeurs sont copiées depuis la base et de les garder synchronisées. Vous pouvez aider cela avec des commentaires de code. C'est une autre raison pour laquelle dans la base de données lors du stockage desenum
valeurs, je stocke toujours la chaîne, pas la valeur. Parce que si vous utilisez des valeurs entières croissantes attribuées automatiquement, celles-ci peuvent changer avec le temps.la source
SmallMedium = 100,
), afin de pouvoir conserver la compatibilité avec les anciennes versions de votre logiciel lorsque vous ajoutez de nouvelles valeurs dans la classe de base. Par exemple, l'ajout d'uneHuge
taille dans votre énumération de base attribuerait4
à sa valeur, mais4
est déjà repris parSmallMedium
dans la classe dérivée.Huge
de la classe de base nécessiterait unHuge
dans la sous-classe avantSmallMedium
BaseBall
peut-être pas le nom le plus intelligent ici. C'est confus. Depuis un baseball est en fait une chose. Si vous manquez qu'il ne s'agit que d'une classe de base pour le ballon, il semble très étrange qu'un volley-ball hérite d'un baseball physiquement plus petit :). Ma suggestion est d'utiliser simplementBall
Solution alternative
Dans mon entreprise, nous évitons de «sauter par-dessus les projets» pour accéder à des projets de niveau inférieur non communs. Par exemple, notre couche présentation / API ne peut référencer que notre couche domaine, et la couche domaine ne peut référencer que la couche données.
Toutefois, cela pose problème lorsqu'il existe des énumérations qui doivent être référencées à la fois par la présentation et les couches de domaine.
Voici la solution que nous avons implémentée (jusqu'à présent). C'est une assez bonne solution et fonctionne bien pour nous. Les autres réponses frappaient tout autour.
La prémisse de base est que les énumérations ne peuvent pas être héritées - mais les classes le peuvent. Donc...
Ensuite, pour "hériter" des énumérations dans un autre projet de niveau supérieur ...
Cela présente trois avantages réels ...
Pour référencer les énumérations dans le premier projet , vous pouvez utiliser le préfixe de la classe: BaseEnums.StatusType.Pending ou ajouter un "using static BaseEnums;" déclaration à vos utilisations.
Cependant, dans le deuxième projet, lorsque je traitais avec la classe héritée, je ne pouvais pas faire fonctionner l'approche "using static ..." , donc toutes les références aux "énumérations héritées" seraient préfixées avec la classe, par exemple SubEnums.StatusType.Pending . Si quelqu'un trouve un moyen d'autoriser l' utilisation de l' approche "en utilisant statique" dans le deuxième projet, faites-le moi savoir.
Je suis sûr que cela peut être modifié pour le rendre encore meilleur - mais cela fonctionne réellement et j'ai utilisé cette approche dans des projets de travail.
Veuillez voter positivement si vous le jugez utile.
la source
J'ai également voulu surcharger Enums et créé un mélange de la réponse de 'Seven' sur cette page et de la réponse de 'Merlyn Morgan-Graham' sur un article en double de ceci , plus quelques améliorations.
Principaux avantages de ma solution par rapport aux autres:
Il s'agit d'une solution prête à l'emploi et peut être directement insérée dans votre projet. Il est conçu pour mes besoins, donc si vous n'aimez pas certaines parties, remplacez-les simplement par votre propre code.
Tout d'abord, il y a la classe de base
CEnum
dont toutes les énumérations personnalisées doivent hériter. Il a la fonctionnalité de base, similaire auEnum
type .net :Deuxièmement, voici 2 classes Enum dérivées. Toutes les classes dérivées ont besoin de quelques méthodes de base pour fonctionner comme prévu. C'est toujours le même code passe-partout; Je n'ai pas encore trouvé de moyen de l'externaliser à la classe de base. Le code du premier niveau d'héritage diffère légèrement de tous les niveaux suivants.
Les classes ont été testées avec succès avec le code suivant:
la source
Les énumérations ne sont pas des classes réelles, même si elles y ressemblent. En interne, ils sont traités comme leur type sous-jacent (par défaut Int32). Par conséquent, vous ne pouvez le faire qu'en "copiant" des valeurs uniques d'une énumération à une autre et en les convertissant en leur nombre entier pour les comparer pour l'égalité.
la source
Les énumérations ne peuvent pas être dérivées d'autres énumérations, mais uniquement de int, uint, short, ushort, long, ulong, byte et sbyte.
Comme Pascal l'a dit, vous pouvez utiliser d'autres valeurs ou constantes d'énumération pour initialiser une valeur d'énumération, mais c'est tout.
la source
une autre solution possible:
HTH
la source
Ce n'est pas possible (comme @JaredPar déjà mentionné). Essayer de mettre la logique autour de cela est une mauvaise pratique. Si vous avez un
base class
qui ont unenum
, vous devez la liste de tous les possiblesenum-values
là - bas, et la mise en œuvre de la classe doit travailler avec les valeurs qu'il connaît.Par exemple, supposons que vous ayez une classe de base
BaseCatalog
et qu'elle ait unenum ProductFormats
(Digital
,Physical
). Ensuite, vous pouvez avoir unMusicCatalog
ouBookCatalog
qui pourrait contenir à la foisDigital
et desPhysical
produits, mais si la classe estClothingCatalog
, elle ne doit contenir que desPhysical
produits.la source
Je me rends compte que je suis un peu en retard à cette fête, mais voici mes deux cents.
Nous savons tous clairement que l'héritage Enum n'est pas pris en charge par le cadre. Certaines solutions de contournement très intéressantes ont été suggérées dans ce fil de discussion, mais aucun d'entre eux ne ressemblait tout à fait à ce que je cherchais, alors j'ai moi-même essayé.
Présentation: ObjectEnum
Vous pouvez vérifier le code et la documentation ici: https://github.com/dimi3tron/ObjectEnum .
Et le package ici: https://www.nuget.org/packages/ObjectEnum
Ou installez-le simplement:
Install-Package ObjectEnum
En bref,
ObjectEnum<TEnum>
agit comme un wrapper pour toute énumération. En remplaçant GetDefinedValues () dans les sous-classes, on peut spécifier quelles valeurs d'énumération sont valides pour cette classe spécifique.Un certain nombre de surcharges d’opérateurs ont été ajoutées pour
ObjectEnum<TEnum>
instance se comporte comme si elle était une instance de l'énumération sous-jacente, en gardant à l'esprit les restrictions de valeur définies. Cela signifie que vous pouvez facilement comparer l'instance à une valeur int ou enum, et donc l'utiliser dans un cas de commutateur ou tout autre conditionnel.Je voudrais me référer à la mention de dépôt github ci-dessus pour des exemples et des informations supplémentaires.
J'espère que vous trouvez ça utile. N'hésitez pas à commenter ou à ouvrir un problème sur github pour d'autres réflexions ou commentaires.
Voici quelques exemples de ce que vous pouvez faire avec
ObjectEnum<TEnum>
:la source
Vous pouvez effectuer l'héritage dans enum, mais il est limité aux types suivants uniquement. int, uint, octet, sbyte, court, ushort, long, ulong
Par exemple
la source