Obter valor int de enum em C #
Pergunta
Eu tenho uma classe chamada Questions
(plural). Nesta classe há um enum chamado Question
(singular) que se parece com isso.
public enum Question
{
Role = 2,
ProjectFunding = 3,
TotalEmployee = 4,
NumberOfServers = 5,
TopBusinessConcern = 6
}
Na classe Questions
, eu tenho uma função get(int foo)
que retorna um objeto Questions
para que foo
. Existe uma maneira fácil de obter o valor inteiro do enum para que eu possa fazer algo como Questions.Get(Question.Role)
?
Solução
Apenas lançar a enumeração, por exemplo.
int something = (int) Question.Role;
O trabalho vontade acima para a grande maioria dos enums você vê na natureza, como o tipo subjacente padrão para um enum é int
.
No entanto, como cecilphillip aponta, enums pode ter diferentes tipos subjacentes.
Se um ENUM é declarado como um uint
, long
, ou ulong
, ele deve ser convertido para o tipo de enumeração; por exemplo. para
enum StarsInMilkyWay:long {Sun = 1, V645Centauri = 2 .. Wolf424B = 2147483649};
você deve usar
long something = (long)StarsInMilkyWay.Wolf424B;
Outras dicas
Desde Enums pode ser qualquer tipo integral (byte
, int
, short
, etc.), uma forma mais robusta para obter o valor integral subjacente da enumeração seria fazer uso do método GetTypeCode
em conjunto com a classe Convert
:
enum Sides {
Left, Right, Top, Bottom
}
Sides side = Sides.Bottom;
object val = Convert.ChangeType(side, side.GetTypeCode());
Console.WriteLine(val);
Isso deve funcionar independentemente do tipo integral subjacente.
declará-lo como uma classe estática tendo constantes públicas:
public static class Question
{
public const int Role = 2;
public const int ProjectFunding = 3;
public const int TotalEmployee = 4;
public const int NumberOfServers = 5;
public const int TopBusinessConcern = 6;
}
E então você pode referenciá-lo como Question.Role
, e sempre avaliada como um int
ou o que você defini-lo como.
Question question = Question.Role;
int value = (int) question;
resultará na value == 2
.
Em uma nota relacionada, se você quiser obter o valor int
de System.Enum
, então, dado e
aqui:
Enum e = Question.Role;
Você pode usar:
int i = Convert.ToInt32(e);
int i = (int)(object)e;
int i = (int)Enum.Parse(e.GetType(), e.ToString());
int i = (int)Enum.ToObject(e.GetType(), e);
Os dois últimos são feio. Eu prefiro a primeira.
É mais fácil do que você pensa - uma enumeração já é um int. Ele só precisa ser lembrado:
int y = (int)Question.Role;
Console.WriteLine(y); // prints 2
Exemplo:
public Enum EmpNo
{
Raj = 1,
Rahul,
Priyanka
}
E no código por trás para obter o valor enum:
int setempNo = (int)EmpNo.Raj; //This will give setempNo = 1
ou
int setempNo = (int)EmpNo.Rahul; //This will give setempNo = 2
Enums será incrementado por 1, e você pode definir o valor inicial. Se você não definir o valor inicial será atribuído como 0 inicialmente.
Eu recentemente convertido longe de usar enums no meu código em favor de vez o uso de classes com construtores protegidas e instâncias estáticas pré-definido (graças a Roelof - C # Certifique-se de valores eNUM válidos-enum valores-valid-futureproof-método -sharp-garantir--. método Futureproof )
À luz do que, abaixo de como eu agora abordar esta questão (incluindo a conversão implícita de / para int
).
public class Question
{
// Attributes
protected int index;
protected string name;
// Go with a dictionary to enforce unique index
//protected static readonly ICollection<Question> values = new Collection<Question>();
protected static readonly IDictionary<int,Question> values = new Dictionary<int,Question>();
// Define the "enum" values
public static readonly Question Role = new Question(2,"Role");
public static readonly Question ProjectFunding = new Question(3, "Project Funding");
public static readonly Question TotalEmployee = new Question(4, "Total Employee");
public static readonly Question NumberOfServers = new Question(5, "Number of Servers");
public static readonly Question TopBusinessConcern = new Question(6, "Top Business Concern");
// Constructors
protected Question(int index, string name)
{
this.index = index;
this.name = name;
values.Add(index, this);
}
// Easy int conversion
public static implicit operator int(Question question) =>
question.index; //nb: if question is null this will return a null pointer exception
public static implicit operator Question(int index) =>
values.TryGetValue(index, out var question) ? question : null;
// Easy string conversion (also update ToString for the same effect)
public override string ToString() =>
this.name;
public static implicit operator string(Question question) =>
question?.ToString();
public static implicit operator Question(string name) =>
name == null ? null : values.Values.FirstOrDefault(item => name.Equals(item.name, StringComparison.CurrentCultureIgnoreCase));
// If you specifically want a Get(int x) function (though not required given the implicit converstion)
public Question Get(int foo) =>
foo; //(implicit conversion will take care of the conversion for you)
}
A vantagem dessa abordagem é que você começa tudo que você tem a partir do enum, mas o código é agora muito mais flexível, de modo que você deve precisar executar ações diferentes com base no valor de Question
, você pode colocar lógica em si Question
( ou seja, na forma OO preferido) em oposição a colocar lotes de declarações de casos em todo o código para lidar com cada cenário.
NB: Resposta atualizados 2018/04/27 fazer uso de C # 6 características; ou seja, expressões de declaração e definições do corpo de expressão lambda. Consulte histórico de revisão href="https://stackoverflow.com/posts/15713789/revisions"> de código original. Isto tem a vantagem de fazer a definição um pouco menos detalhado; que tinha sido uma das principais queixas sobre abordagem desta resposta.
Se você deseja obter um inteiro para o valor de enumeração que é armazenado em uma variável, wich o tipo seria Question
, para usar, por exemplo, em um método, você pode simplesmente fazer isso eu escrevi neste exemplo:
enum Talen
{
Engels = 1, Italiaans = 2, Portugees = 3, Nederlands = 4, Duits = 5, Dens = 6
}
Talen Geselecteerd;
public void Form1()
{
InitializeComponent()
Geselecteerd = Talen.Nederlands;
}
// You can use the Enum type as a parameter, so any enumeration from any enumerator can be used as parameter
void VeranderenTitel(Enum e)
{
this.Text = Convert.ToInt32(e).ToString();
}
Isso irá alterar o título da janela para 4 porque o Geselecteerd
variável é Talen.Nederlands
. Se eu mudar para Talen.Portugees
e chamar o método novamente, o texto será alterado para 3.
Eu tive um tempo difícil para encontrar este simples solução na internet e eu não poderia encontrá-lo, então eu estava testando algo e descobriu isso. Espero que isto ajude. ;)
Para garantir um valor de enumeração existe e, em seguida, analisá-lo, você também pode fazer o seguinte.
// Fake Day of Week
string strDOWFake = "SuperDay";
// Real Day of Week
string strDOWReal = "Friday";
// Will hold which ever is the real DOW.
DayOfWeek enmDOW;
// See if fake DOW is defined in the DayOfWeek enumeration.
if (Enum.IsDefined(typeof(DayOfWeek), strDOWFake))
{
// This will never be reached since "SuperDay"
// doesn't exist in the DayOfWeek enumeration.
enmDOW = (DayOfWeek)Enum.Parse(typeof(DayOfWeek), strDOWFake);
}
// See if real DOW is defined in the DayOfWeek enumeration.
else if (Enum.IsDefined(typeof(DayOfWeek), strDOWReal))
{
// This will parse the string into it's corresponding DOW enum object.
enmDOW = (DayOfWeek)Enum.Parse(typeof(DayOfWeek), strDOWReal);
}
// Can now use the DOW enum object.
Console.Write("Today is " + enmDOW.ToString() + ".");
Espero que isso ajude.
Talvez eu perdi, mas tem alguém tentou um método de extensão genérica simples. Isso funciona muito bem para mim. Você pode evitar o tipo de elenco em sua API desta forma, mas em última análise, resulta em uma operação tipo de alteração. Este é um bom caso para a programação Roselyn ter o compilador fazer um método GetValue para você.
public static void Main()
{
int test = MyCSharpWrapperMethod(TestEnum.Test1);
Debug.Assert(test == 1);
}
public static int MyCSharpWrapperMethod(TestEnum customFlag)
{
return MyCPlusPlusMethod(customFlag.GetValue<int>());
}
public static int MyCPlusPlusMethod(int customFlag)
{
//Pretend you made a PInvoke or COM+ call to C++ method that require an integer
return customFlag;
}
public enum TestEnum
{
Test1 = 1,
Test2 = 2,
Test3 = 3
}
}
public static class EnumExtensions
{
public static T GetValue<T>(this Enum enumeration)
{
T result = default(T);
try
{
result = (T)Convert.ChangeType(enumeration, typeof(T));
}
catch (Exception ex)
{
Debug.Assert(false);
Debug.WriteLine(ex);
}
return result;
}
}
Mais uma maneira de fazê-lo:
Console.WriteLine("Name: {0}, Value: {0:D}", Question.Role);
resultará em:
Name: Role, Value: 2
public enum QuestionType
{
Role = 2,
ProjectFunding = 3,
TotalEmployee = 4,
NumberOfServers = 5,
TopBusinessConcern = 6
}
... é uma declaração bem.
Você tem que converter o resultado para int assim:
int Question = (int)QuestionType.Role
Caso contrário, o tipo ainda é QuestionType
.
Este nível de rigor é o C # forma.
Uma alternativa é usar uma declaração de classe em vez disso:
public class QuestionType
{
public static int Role = 2,
public static int ProjectFunding = 3,
public static int TotalEmployee = 4,
public static int NumberOfServers = 5,
public static int TopBusinessConcern = 6
}
É menos elegante para declarar, mas você não precisa lançá-lo em código:
int Question = QuestionType.Role
Como alternativa, você pode se sentir mais confortável com o Visual Basic, que atende a esse tipo de expectativa em muitas áreas.
Você pode fazer isso através da implementação de um Método de extensão para o seu tipo de enum definido:
public static class MyExtensions
{
public static int getNumberValue(this Question questionThis)
{
return (int)questionThis;
}
}
Esta simplificar recebendo o valor int de valor de enumeração atual:
Question question = Question.Role;
int value = question.getNumberValue();
ou
int value = Question.Role.getNumberValue();
int number = Question.Role.GetHashCode();
number
deve ter o valor 2
.
Como cerca de um método de extensão em vez disso:
public static class ExtensionMethods
{
public static int IntValue(this Enum argEnum)
{
return Convert.ToInt32(argEnum);
}
}
E o uso é ligeiramente mais bonito:
var intValue = Question.Role.IntValue();
public enum Suit : int
{
Spades = 0,
Hearts = 1,
Clubs = 2,
Diamonds = 3
}
Console.WriteLine((int)(Suit)Enum.Parse(typeof(Suit), "Clubs"));
//from int
Console.WriteLine((Suit)1);
//From number you can also
Console.WriteLine((Suit)Enum.ToObject(typeof(Suit), 1));
if (typeof(Suit).IsEnumDefined("Spades"))
{
var res = (int)(Suit)Enum.Parse(typeof(Suit), "Spades");
Console.Out.WriteLine("{0}", res);
}
My fav corte com int ou enums menores:
GetHashCode();
Para um enum
public enum Test
{
Min = Int32.MinValue,
One = 1,
Max = Int32.MaxValue,
}
este
var values = Enum.GetValues(typeof(Test));
foreach (var val in values)
{
Console.WriteLine(val.GetHashCode());
Console.WriteLine(((int)val));
Console.WriteLine(val);
}
saídas
one
1
1
max
2147483647
2147483647
min
-2147483648
-2147483648
Disclaimer: Não funciona para enums com base no longo
Segue-se o método de extensão
public static string ToEnumString<TEnum>(this int enumValue)
{
var enumString = enumValue.ToString();
if (Enum.IsDefined(typeof(TEnum), enumValue))
{
enumString = ((TEnum) Enum.ToObject(typeof (TEnum), enumValue)).ToString();
}
return enumString;
}
Desde enums podem ser declarados com vários tipos primitivos, um método de extensão genérica para lançar qualquer tipo de enumeração pode ser útil.
enum Box
{
HEIGHT,
WIDTH,
DEPTH
}
public static void UseEnum()
{
int height = Box.HEIGHT.GetEnumValue<int>();
int width = Box.WIDTH.GetEnumValue<int>();
int depth = Box.DEPTH.GetEnumValue<int>();
}
public static T GetEnumValue<T>(this object e) => (T)e;
O exemplo que eu gostaria de sugerir 'para obter 'int' valor de enum é,'
public enum Sample
{Book =1, Pen=2, Pencil =3}
int answer = (int)Sample.Book;
Agora, a resposta será 1.
Espero que isso possa ajudar alguém.
A solução mais fácil que eu posso pensar é sobrecarregar o método Get(int)
assim:
[modifiers] Questions Get(Question q)
{
return Get((int)q);
}
onde [modifiers]
geralmente pode ser o mesmo que para o método Get(int)
. Se você não pode editar a classe Questions
ou por algum motivo não quer, você pode sobrecarregar o método escrevendo uma extensão:
public static class Extensions
{
public static Questions Get(this Questions qs, Question q)
{
return qs.Get((int)q);
}
}
Tente este em vez de converter enum para int:
public static class ReturnType
{
public static readonly int Success = 1;
public static readonly int Duplicate = 2;
public static readonly int Error = -1;
}
Em VB. Deve ser
Public Enum Question
Role = 2
ProjectFunding = 3
TotalEmployee = 4
NumberOfServers = 5
TopBusinessConcern = 6
End Enum
Private value As Integer = CInt(Question.Role)
Eu um pouco tarde para o jogo, mas eu vim com esse método de extensão que inclui recursos de linguagem corrente. Usando dinâmica, eu não preciso para tornar este um método genérico e especificar o tipo que mantém a invocação mais simples e consistente. Por favor, deixe-me saber se eu fiz algo errado:
public static class EnumEx
{
public static dynamic Value(this Enum e)
{
switch (e.GetTypeCode())
{
case TypeCode.Byte:
{
return (byte) (IConvertible) e;
}
case TypeCode.Int16:
{
return (short) (IConvertible) e;
}
case TypeCode.Int32:
{
return (int) (IConvertible) e;
}
case TypeCode.Int64:
{
return (long) (IConvertible) e;
}
case TypeCode.UInt16:
{
return (ushort) (IConvertible) e;
}
case TypeCode.UInt32:
{
return (uint) (IConvertible) e;
}
case TypeCode.UInt64:
{
return (ulong) (IConvertible) e;
}
case TypeCode.SByte:
{
return (sbyte) (IConvertible) e;
}
}
return 0;
}
Question question = Question.Role;
int value = question.GetHashCode();
resultará na value == 2
.
Isso só é verdade se os ajustes enum dentro de um
int
Tente isto:
int value = YourEnum.ToString("D");