réponse courte, oui. Dans ce cas précis, vous voudrez peut-être envisager l'utilisation deTimeSpan
Jodrell
1
Utiliser des méthodes d'extension sur une énumération me ferait me sentir sale. Créez une classe pour encapsuler ce qui est nécessaire. Gardez une énumération aussi simple que possible. Si vous avez besoin de plus de logique associée, créez une classe Duration qui expose jour, semaine, mois plus contient toute autre logique qui aurait été dans la méthode d'extension.
Jason Evans
2
J'aime avoir des méthodes d'extension enum pour les groupes d'indicateurs. Je préfère si des clauses par exemple Day.IsWorkday()sur (Day & Days.Workday) > 0des Days.Workdaydéfinis comme Monday | Tuesday ... | Friday. Le premier est plus clair à mon avis et a exactement le second mis en œuvre.
Les méthodes d'extension fournissent un moyen d'écrire des méthodes pour des classes existantes d'une manière que d'autres personnes de votre équipe pourraient réellement découvrir et utiliser. Étant donné que les énumérations sont des classes comme les autres, il ne devrait pas être trop surprenant que vous puissiez les étendre, comme:
Je pense que les énumérations ne sont pas le meilleur choix en général, mais au moins cela vous permet de centraliser une partie de la gestion des commutateurs / if et de les abstraire un peu jusqu'à ce que vous puissiez faire quelque chose de mieux. N'oubliez pas de vérifier que les valeurs sont également comprises.
Je crois que le commentaire "enums are evil" est déplacé mais a un fondement dans la réalité. Je trouve que les énumérations peuvent être un problème surutilisées, car elles vous enferment en quelque sorte dans certains contextes et comportements.
Ed Schwehm
1
Les énumérations en C # sont nulles parce que cela compile et s'exécute:Duration d = 0;
Graham
16
Given that enums are classesnon ce ne sont pas des cours.
Ailier Sendon
1
J'utilise ce type d'extension uniquement s'il s'agit directement de l'énumération, comme les jours de la semaine et les méthodes d'extension IsWeekday (), IsWeekendday (). Mais les classes sont destinées à encapsuler des comportements, donc s'il y a beaucoup de comportements compliqués à encapsuler, une classe est probablement meilleure. Si c'est limité et basique, je trouve personnellement que les extensions sur les énumérations sont correctes. Comme pour la plupart des décisions de conception, il existe des frontières floues entre les choix (IMO). Il convient de noter que les extensions ne peuvent être effectuées que sur des classes statiques de niveau supérieur, pas sur des classes imbriquées. Si votre énumération fait partie d'une classe, vous devrez créer une classe.
FreeText
51
Vous pouvez également ajouter une méthode d'extension au type Enum plutôt qu'une instance de Enum:
/// <summary> Enum Extension Methods </summary>/// <typeparam name="T"> type of Enum </typeparam>publicclassEnum<T>where T :struct,IConvertible{publicstaticintCount{get{if(!typeof(T).IsEnum)thrownewArgumentException("T must be an enumerated type");returnEnum.GetNames(typeof(T)).Length;}}}
Vous pouvez appeler la méthode d'extension ci-dessus en faisant:
var result =Enum<Duration>.Count;
Ce n'est pas une véritable méthode d'extension. Cela fonctionne uniquement car Enum <> est d'un type différent de System.Enum.
La classe peut-elle statics'assurer que toutes ses méthodes se comportent comme des extensions?
Jatin Sanghvi
15
Pour les futurs lecteurs: l'ambiguïté du nom de Enum<T>est un peu déroutante. La classe pourrait également être appelée EnumUtils<T>et l'appel de méthode se résoudrait en EnumUtils<Duration>.Count.
Namoshek
46
Bien sûr, vous pouvez, par exemple, utiliser le DescriptionAttribuesur vos enumvaleurs:
using System.ComponentModel.DataAnnotations;publicenumDuration{[Description("Eight hours")]Day,[Description("Five days")]Week,[Description("Twenty-one days")]Month}
Vous voulez maintenant pouvoir faire quelque chose comme:
Duration duration =Duration.Week;var description = duration.GetDescription();// will return "Five days"
Votre méthode d'extension GetDescription()peut être écrite comme suit:
using System.ComponentModel;
using System.Reflection;publicstaticstringGetDescription(thisEnumvalue){FieldInfo fieldInfo =value.GetType().GetField(value.ToString());if(fieldInfo ==null)returnnull;var attribute =(DescriptionAttribute)fieldInfo.GetCustomAttribute(typeof(DescriptionAttribute));return attribute.Description;}
Je cherchais à créer une extension pour presque exactement ce que vous avez fait, sauf mon utilisation de DisplayAttribute Localized GetDescription. cheers
George
C'est une bonne alternative, même si je pense que l'espace de noms est juste System.ComponentModel?
TomDestry
Belle perspective et merci d'avoir montré l'implémentation ainsi que le code d'extension. Pour empiler: avec votre implémentation, vous pouvez également l'appeler comme ceci: var description = Duration.Week.GetDescription ();
Spencer Sullivan
31
Toutes les réponses sont excellentes, mais elles parlent d'ajouter une méthode d'extension à un type spécifique d'énumération.
Que faire si vous souhaitez ajouter une méthode à toutes les énumérations, comme renvoyer un int de la valeur actuelle au lieu d'un cast explicite?
publicstaticclassEnumExtensions{publicstaticintToInt<T>(this T soure)where T :IConvertible//enum{if(!typeof(T).IsEnum)thrownewArgumentException("T must be an enumerated type");return(int)(IConvertible) soure;}//ShawnFeatherly funtion (above answer) but as extention methodpublicstaticintCount<T>(this T soure)where T :IConvertible//enum{if(!typeof(T).IsEnum)thrownewArgumentException("T must be an enumerated type");returnEnum.GetNames(typeof(T)).Length;}}
L'astuce derrière IConvertibleest sa hiérarchie d'héritage voir MDSN
Idem. Cela fonctionne si j'appelle l'extension directement (par exemple MyExtention.DoThing(myvalue)) mais ne m'attache pas réellement à l'énumération (par exemple myvalue.DoThing())
Sinaesthetic
1
FYI, C # 7.3 prend désormais en charge Enum en tant que contrainte de type générique
redtetrahedron
7
Vous pouvez créer une extension pour n'importe quoi, même object(bien que ce ne soit pas considéré comme une meilleure pratique ). Comprenez une méthode d'extension comme une public staticméthode. Vous pouvez utiliser le type de paramètre de votre choix sur les méthodes.
Une voidvaleur de retour sur une énumération est un peu bizarre. Je penserais à un échantillon plus réaliste.
psubsee2003
3
@ psubsee2003 l'OP a sûrement assez de connaissances pour changer cela en fonction de ses besoins? Pourquoi l'échantillon est-il important, il suffit de répondre à la question initiale.
LukeHennerley
3
Suis-je le seul à trouver bizarre les exemples de code sur MSDN? La plupart du temps, vous avez besoin d'un réel effort pour comprendre ce qu'ils essaient de faire!
TimeSpan
Day.IsWorkday()
sur(Day & Days.Workday) > 0
desDays.Workday
définis commeMonday | Tuesday ... | Friday
. Le premier est plus clair à mon avis et a exactement le second mis en œuvre.Réponses:
Selon ce site :
Les méthodes d'extension fournissent un moyen d'écrire des méthodes pour des classes existantes d'une manière que d'autres personnes de votre équipe pourraient réellement découvrir et utiliser. Étant donné que les énumérations sont des classes comme les autres, il ne devrait pas être trop surprenant que vous puissiez les étendre, comme:
Je pense que les énumérations ne sont pas le meilleur choix en général, mais au moins cela vous permet de centraliser une partie de la gestion des commutateurs / if et de les abstraire un peu jusqu'à ce que vous puissiez faire quelque chose de mieux. N'oubliez pas de vérifier que les valeurs sont également comprises.
Vous pouvez en savoir plus ici sur Microsft MSDN.
la source
Duration d = 0;
Given that enums are classes
non ce ne sont pas des cours.Vous pouvez également ajouter une méthode d'extension au type Enum plutôt qu'une instance de Enum:
Vous pouvez appeler la méthode d'extension ci-dessus en faisant:
Ce n'est pas une véritable méthode d'extension. Cela fonctionne uniquement car Enum <> est d'un type différent de System.Enum.
la source
static
s'assurer que toutes ses méthodes se comportent comme des extensions?Enum<T>
est un peu déroutante. La classe pourrait également être appeléeEnumUtils<T>
et l'appel de méthode se résoudrait enEnumUtils<Duration>.Count
.Bien sûr, vous pouvez, par exemple, utiliser le
DescriptionAttribue
sur vosenum
valeurs:Vous voulez maintenant pouvoir faire quelque chose comme:
Votre méthode d'extension
GetDescription()
peut être écrite comme suit:la source
Toutes les réponses sont excellentes, mais elles parlent d'ajouter une méthode d'extension à un type spécifique d'énumération.
Que faire si vous souhaitez ajouter une méthode à toutes les énumérations, comme renvoyer un int de la valeur actuelle au lieu d'un cast explicite?
L'astuce derrière
IConvertible
est sa hiérarchie d'héritage voir MDSNMerci à ShawnFeatherly pour sa réponse
la source
MyExtention.DoThing(myvalue)
) mais ne m'attache pas réellement à l'énumération (par exemplemyvalue.DoThing()
)Vous pouvez créer une extension pour n'importe quoi, même
object
(bien que ce ne soit pas considéré comme une meilleure pratique ). Comprenez une méthode d'extension comme unepublic static
méthode. Vous pouvez utiliser le type de paramètre de votre choix sur les méthodes.la source
Voir MSDN .
la source
void
valeur de retour sur une énumération est un peu bizarre. Je penserais à un échantillon plus réaliste.nous venons de créer une extension enum pour c # https://github.com/simonmau/enum_ext
C'est juste une implémentation pour le typesafeenum, mais cela fonctionne très bien, nous avons donc créé un package à partager - amusez-vous avec
Je sais que l'exemple est un peu inutile, mais vous voyez l'idée;)
la source
Une solution de contournement simple.
la source