resposta curta, sim. Neste caso específico, você pode querer considerar o uso deTimeSpan
Jodrell
1
Usar métodos de extensão em uma enumeração me faria sentir suja. Crie uma classe para encapsular o que é necessário. Mantenha uma enumeração o mais simples possível. Se você precisar de mais lógica associada, crie uma classe Duration que exponha dia, semana, mês e mais qualquer outra lógica que estivesse no método de extensão.
Jason Evans
2
Eu gosto de ter métodos de extensão de enumeração para grupos de sinalizadores. Eu prefiro em se cláusulas por exemplo Day.IsWorkday()sobre (Day & Days.Workday) > 0com Days.Workdaydefinido como Monday | Tuesday ... | Friday. O primeiro é mais claro na minha opinião e implementou exatamente o último.
Os métodos de extensão fornecem uma maneira de escrever métodos para as classes existentes de uma maneira que outras pessoas da sua equipe possam descobrir e usar. Dado que enums são classes como qualquer outra, não deve ser muito surpreendente que você possa estendê-las, como:
Eu acho que enums não são a melhor escolha em geral, mas pelo menos isso permite centralizar parte do switch / se manipular e abstraí-los um pouco até que você possa fazer algo melhor. Lembre-se de verificar se os valores também estão no intervalo.
Acredito que o comentário "enums é mau" está fora de lugar, mas tem uma base na realidade. Eu acho que as enums podem ser um problema que é usado em excesso, pois elas meio que prendem você em certos contextos e comportamentos.
Ed Schwehm
1
Enums em C # tipo de chupar porque este compila e roda:Duration d = 0;
Graham
16
Given that enums are classesnão, eles não são classes.
Winger Sendon
1
Eu uso esse tipo de extensão apenas se for sobre o enum diretamente, como dias da semana e métodos de extensão IsWeekday (), IsWeekendday (). Mas as classes têm o objetivo de encapsular comportamentos; portanto, se há muitos ou comportamentos complicados para encapsular, uma classe provavelmente é melhor. Se é limitado e básico, eu pessoalmente acho que extensões em enumerações são boas. Como na maioria das decisões de design, existem limites difusos entre escolhas (IMO). Vale ressaltar que as extensões só podem ser feitas nas classes estáticas de nível superior, e não nas classes aninhadas. Se sua enumeração faz parte de uma classe, você precisará fazer uma aula.
FreeText
51
Você também pode adicionar um método de extensão ao tipo Enum, em vez de uma instância do 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;}}}
Você pode invocar o método de extensão acima fazendo:
var result =Enum<Duration>.Count;
Não é um verdadeiro método de extensão. Funciona apenas porque Enum <> é um tipo diferente de System.Enum.
A classe staticpode garantir que todos os seus métodos se comportem como extensões?
Jatin Sanghvi
15
Para futuros leitores: a ambiguidade do nome Enum<T>é um pouco confusa. A classe também pode ser chamada EnumUtils<T>e a chamada do método seria resolvida EnumUtils<Duration>.Count.
Namoshek 27/02/19
46
Claro que você pode, digamos, por exemplo, que você queira usar o valor DescriptionAttribueem seus enumvalores:
using System.ComponentModel.DataAnnotations;publicenumDuration{[Description("Eight hours")]Day,[Description("Five days")]Week,[Description("Twenty-one days")]Month}
Agora você deseja poder fazer algo como:
Duration duration =Duration.Week;var description = duration.GetDescription();// will return "Five days"
Seu método de extensão GetDescription()pode ser escrito da seguinte maneira:
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;}
Eu estava olhando para criar uma extensão para quase exatamente o que você fez, exceto o meu uso DisplayAttribute Localized GetDescription. Cheers
George
Essa é uma boa alternativa, embora eu ache que o espaço para nome seja apenas System.ComponentModel?
TomDestry
Boa perspectiva e obrigado por mostrar a implementação e o código de extensão. Para acumular: com sua implementação, você também pode chamá-lo assim: var description = Duration.Week.GetDescription ();
Spencer Sullivan
30
Todas as respostas são ótimas, mas elas estão falando sobre adicionar um método de extensão a um tipo específico de enumeração.
E se você quiser adicionar um método a todas as enumerações, como retornar um int do valor atual, em vez da conversão explícita?
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;}}
O truque por trás IConvertibleé sua hierarquia de herança, veja MDSN
Idem. Ele funciona se eu chamar a extensão diretamente (por exemplo MyExtention.DoThing(myvalue)), mas na verdade não atribuem à enumeração (por exemplo myvalue.DoThing())
Sinaesthetic
1
FYI, C # 7.3 agora suporta Enum como um tipo de restrição genérica
redtetrahedron
7
Você pode criar uma extensão para qualquer coisa, mesmo object(embora isso não seja considerado uma prática recomendada ). Entenda um método de extensão como um public staticmétodo. Você pode usar qualquer tipo de parâmetro que desejar nos métodos.
Um voidvalor de retorno em uma enumeração é meio estranho. Eu pensaria em uma amostra mais realista.
psubsee2003
3
@ psubsee2003 o OP certamente tem conhecimento suficiente para mudar isso para atender às suas necessidades? Por que a amostra importa, basta responder à pergunta inicial.
LukeHennerley
3
Eu sou o único que acha os exemplos de código no MSDN estranhos? Na maioria das vezes, você precisa de algum esforço real para entender o que eles estão tentando fazer!
TimeSpan
Day.IsWorkday()
sobre(Day & Days.Workday) > 0
comDays.Workday
definido comoMonday | Tuesday ... | Friday
. O primeiro é mais claro na minha opinião e implementou exatamente o último.Respostas:
De acordo com este site :
Os métodos de extensão fornecem uma maneira de escrever métodos para as classes existentes de uma maneira que outras pessoas da sua equipe possam descobrir e usar. Dado que enums são classes como qualquer outra, não deve ser muito surpreendente que você possa estendê-las, como:
Eu acho que enums não são a melhor escolha em geral, mas pelo menos isso permite centralizar parte do switch / se manipular e abstraí-los um pouco até que você possa fazer algo melhor. Lembre-se de verificar se os valores também estão no intervalo.
Você pode ler mais aqui no Microsft MSDN.
fonte
Duration d = 0;
Given that enums are classes
não, eles não são classes.Você também pode adicionar um método de extensão ao tipo Enum, em vez de uma instância do Enum:
Você pode invocar o método de extensão acima fazendo:
Não é um verdadeiro método de extensão. Funciona apenas porque Enum <> é um tipo diferente de System.Enum.
fonte
static
pode garantir que todos os seus métodos se comportem como extensões?Enum<T>
é um pouco confusa. A classe também pode ser chamadaEnumUtils<T>
e a chamada do método seria resolvidaEnumUtils<Duration>.Count
.Claro que você pode, digamos, por exemplo, que você queira usar o valor
DescriptionAttribue
em seusenum
valores:Agora você deseja poder fazer algo como:
Seu método de extensão
GetDescription()
pode ser escrito da seguinte maneira:fonte
Todas as respostas são ótimas, mas elas estão falando sobre adicionar um método de extensão a um tipo específico de enumeração.
E se você quiser adicionar um método a todas as enumerações, como retornar um int do valor atual, em vez da conversão explícita?
O truque por trás
IConvertible
é sua hierarquia de herança, veja MDSNObrigado a ShawnFeatherly por sua resposta
fonte
MyExtention.DoThing(myvalue)
), mas na verdade não atribuem à enumeração (por exemplomyvalue.DoThing()
)Você pode criar uma extensão para qualquer coisa, mesmo
object
(embora isso não seja considerado uma prática recomendada ). Entenda um método de extensão como umpublic static
método. Você pode usar qualquer tipo de parâmetro que desejar nos métodos.fonte
Veja MSDN .
fonte
void
valor de retorno em uma enumeração é meio estranho. Eu pensaria em uma amostra mais realista.acabamos de fazer uma extensão de enum para c # https://github.com/simonmau/enum_ext
É apenas uma implementação para o typesafeenum, mas funciona muito bem, então criamos um pacote para compartilhar - divirta-se com ele
Eu sei que o exemplo é meio inútil, mas você entendeu;)
fonte
Uma solução simples.
fonte