É possível definir uma conversão implícita de enumerações em c #?
algo que poderia conseguir isso?
public enum MyEnum
{
one = 1, two = 2
}
MyEnum number = MyEnum.one;
long i = number;
Se não, por que não?
c#
enums
implicit-conversion
implicit
Adam Naylor
fonte
fonte
enum YesNo {Yes, No}
que pode implicitamente converter em bool.Respostas:
Existe uma solução. Considere o seguinte:
O acima oferece conversão implícita:
Isso é um pouco mais trabalhoso do que declarar uma enum normal (embora você possa refatorar alguns dos itens acima em uma classe base genérica comum). Você pode ir ainda mais longe, fazendo com que a classe base implemente IComparable & IEquatable, além de adicionar métodos para retornar o valor de DescriptionAttributes, nomes declarados, etc.
Eu escrevi uma classe base (RichEnum <>) para lidar com a maioria do trabalho pesado, o que facilita a declaração de enumerações acima para:
A classe base (RichEnum) está listada abaixo.
fonte
Você não pode fazer conversões implícitas (exceto zero) e não pode escrever seus próprios métodos de instância - no entanto, provavelmente pode escrever seus próprios métodos de extensão:
Isso não dá muito, no entanto (comparado a apenas fazer um elenco explícito).
Uma das principais vezes que vi pessoas quererem isso é
[Flags]
manipular via genéricos - isto é, umbool IsFlagSet<T>(T value, T flag);
método. Infelizmente, o C # 3.0 não suporta operadores de genéricos, mas você pode contornar isso usando coisas como esta , que tornam os operadores totalmente disponíveis com genéricos.fonte
fonte
static class
, suponho. Não há vantagem em argumentar em ambos os casos noIL
código final .Adaptei a excelente classe básica genérica RichEnum de Mark.
Fixação
Parabéns a Mark pela excelente idéia + implementação, e aqui estão todos:
Uma amostra de uso que executei em mono:
Produzindo a saída
Nota: o mono 2.6.7 requer uma conversão explícita extra que não é necessária ao usar o mono 2.8.2 ...
fonte
FirstOrDefault
, para evitar assumir que há apenas um único atributo). Se assumir ou não essas coisas é 'uma boa ideia' (ou má , porTDerived instance = (TDerived)field.GetValue(null);
resulta eminstance
sendonull
. Parece que o tempo de execução Mono deve ter uma ordem de tipo de inicialização diferente daquela do .NET que permite que isso funcione. Intrigante! Em vez disso, tive que mover esse código para um método estático e chamá-lo do inicializador de tipo na subclasse.Você não pode declarar conversões implícitas em tipos de enumeração, porque eles não podem definir métodos. A palavra-chave implícita em C # é compilada em um método começando com 'op_', e não funcionaria nesse caso.
fonte
Você provavelmente poderia, mas não para o enum (você não pode adicionar um método a ele). Você pode adicionar uma conversão implícita à sua própria classe para permitir que uma enum seja convertida nela,
A pergunta seria por quê?
Em geral, o .Net evita (e você também deve) qualquer conversão implícita em que os dados possam ser perdidos.
fonte
Se você definir a base da enum como longa, poderá executar uma conversão explícita. Não sei se você pode usar conversões implícitas, pois as enumerações não podem ter métodos definidos nelas.
Além disso, lembre-se disso que uma enumeração não-inicializada será padronizada com o valor 0 ou o primeiro item - portanto, na situação acima, provavelmente seria melhor definir
zero = 0
também.fonte
: long
aqui; a conversão explícita funcionaria bem sem ela. A única conversão implícita legal é zero.enums são em grande parte inúteis para mim por causa disso, OP.
Eu acabo fazendo fotos relacionadas o tempo todo:
a solução simples
Um exemplo clássico de problema é o VirtualKey configurado para detectar pressionamentos de tecla.
O problema aqui é que você não pode indexar a matriz com o enum porque ele não pode converter implicitamente enum em ushort (mesmo que tenhamos baseado o enum em ushort)
nesse contexto específico, as enumerações são obsoletas pela seguinte estrutura de dados. . . .
fonte
Eu resolvi um problema com a resposta de sehe ao executar o código no MS .net (não mono). Para mim, especificamente, o problema ocorreu no .net 4.5.1, mas outras versões também parecem afetadas.
O problema
acessando um
public static TDervied MyEnumValue
pela reflexão (viaFieldInfo.GetValue(null)
que não initialize disse campo.A solução alternativa
Em vez de atribuir nomes a
TDerived
instâncias no inicializador estático,RichEnum<TValue, TDerived>
isso é feito preguiçosamente no primeiro acesso deTDerived.Name
. O código:qual - no meu caso - se baseia em
EquatableBase<T>
:Nota
O código acima não incorpora todos os recursos do Mark resposta original !
obrigado
Agradecemos a Mark por fornecer sua
RichEnum
implementação e a ver por fornecer algumas melhorias!fonte
Encontrei uma solução ainda mais fácil tirada daqui /codereview/7566/enum-vs-int-wrapper-struct Eu colei o código abaixo a partir desse link para o caso de não funcionar no futuro.
fonte
Criei este utilitário para me ajudar a converter um Enum em PrimitiveEnum e PrimitiveEnum em
byte, sbyte, short, ushort, int, uint, long, or ulong
.Portanto, isso tecnicamente converte qualquer enum em qualquer valor primitivo.
Consulte commit em https://github.com/McKabue/McKabue.Extentions.Utility/blob/master/src/McKabue.Extentions.Utility/Enums/PrimitiveEnum.cs
fonte
uint
s que o próprio jogo geralmente criaenum
, mas a estrutura não sabe nada. Ter(uint)
que chamar a estrutura foi uma dor. Sua ideia ao contrário funciona perfeitamente. Em vez destruct
armazenar oEnum
, eu tenho umstruct IdNumber
que armazena o,uint
mas implicitamente converte dos queEnum
o jogo usa. Em vez de digitar os parâmetros da estrutura comouint
, eu posso digitá-losIdNumber
, e a estrutura pode transmiti-los internamente de maneira eficiente, inclusive fazendo operações integradas neles.A introdução de conversões implícitas para tipos de enumeros violaria a segurança de tipos, portanto, eu não recomendo fazer isso. Por que você gostaria de fazer isso? O único caso de uso para isso que eu vi é quando você deseja colocar os valores de enumeração em uma estrutura com um layout predefinido. Mas, mesmo assim, você pode usar o tipo enum na estrutura e apenas dizer ao Marshaller o que ele deve fazer com isso.
fonte