Cast int enum en C#
21 réponses
D'une chaîne de caractères:
YourEnum foo = (YourEnum) Enum.Parse(typeof(YourEnum), yourString);
// the foo.ToString().Contains(",") check is necessary for enumerations marked with an [Flags] attribute
if (!Enum.IsDefined(typeof(YourEnum), foo) && !foo.ToString().Contains(","))
throw new InvalidOperationException($"{yourString} is not an underlying value of the YourEnum enumeration.")
D'un int:
YourEnum foo = (YourEnum)yourInt;
mise à jour:
du numéro vous pouvez aussi
YourEnum foo = (YourEnum)Enum.ToObject(typeof(YourEnum) , yourInt);
Juste de voter pour elle:
MyEnum e = (MyEnum)3;
vous pouvez vérifier si elle est dans la gamme en utilisant Enum.IsDefined :
if (Enum.IsDefined(typeof(MyEnum), 3)) { ... }
alternativement, utiliser une méthode d'extension au lieu d'une doublure unique:
public static T ToEnum<T>(this string enumString)
{
return (T) Enum.Parse(typeof (T), enumString);
}
Utilisation:
Color colorEnum = "Red".ToEnum<Color>();
ou
string color = "Red";
var colorEnum = color.ToEnum<Color>();
je pense que pour obtenir une réponse complète, les gens doivent savoir comment les enums travaillent en interne .NET.
Comment ça marche
un enum dans .NET est une structure qui établit une correspondance entre un ensemble de valeurs (champs) et un type de base (la valeur par défaut est int
). Cependant, vous pouvez réellement choisir le type intégral que votre enum correspond à:
public enum Foo : short
dans ce cas, l'enum est mappé sur les données short
type, ce qui signifie qu'il sera stockée dans la mémoire à court et se comporte comme un court lorsque vous lancez et l'utiliser.
si vous le regardez d'un point de vue IL, un (normal, int) enum ressemble à ceci:
.class public auto ansi serializable sealed BarFlag extends System.Enum
{
.custom instance void System.FlagsAttribute::.ctor()
.custom instance void ComVisibleAttribute::.ctor(bool) = { bool(true) }
.field public static literal valuetype BarFlag AllFlags = int32(0x3fff)
.field public static literal valuetype BarFlag Foo1 = int32(1)
.field public static literal valuetype BarFlag Foo2 = int32(0x2000)
// and so on for all flags or enum values
.field public specialname rtspecialname int32 value__
}
ce qui devrait attirer votre attention ici est que le value__
est stocké séparément des valeurs enum. Dans le cas de l'enum Foo
ci-dessus, le type de value__
est int16. Cela signifie que vous pouvez stocker tout ce que vous voulez dans un enum, aussi longtemps que les types correspondent .
à ce point je voudrais souligner que System.Enum
est un type de valeur, qui signifie essentiellement que BarFlag
prendra 4 octets en mémoire et Foo
prendra 2 -- par exemple la taille du type sous-jacent (c'est en fait plus compliqué que cela, mais bon...).
la réponse
donc, si vous avoir un entier que vous voulez mapper à un enum, l'exécution ne doit faire que 2 choses: copier les 4 octets et lui donner un autre nom (le nom de l'enum). Copier est implicite parce que les données sont stockées comme type de valeur - cela signifie fondamentalement que si vous utilisez du code non géré, vous pouvez simplement échanger des énums et des entiers sans copier des données.
pour être sûr, je pense que c'est une bonne pratique de savoir que les types sous-jacents sont les mêmes ou implicitement convertible et pour s'assurer que les valeurs enum existent (elles ne sont pas vérifiées par défaut!).
Pour voir comment cela fonctionne, essayez le code suivant:
public enum MyEnum : int
{
Foo = 1,
Bar = 2,
Mek = 5
}
static void Main(string[] args)
{
var e1 = (MyEnum)5;
var e2 = (MyEnum)6;
Console.WriteLine("{0} {1}", e1, e2);
Console.ReadLine();
}
notez que le casting de e2
fonctionne aussi! Du point de vue du compilateur ci-dessus, cela a du sens: le champ value__
est simplement rempli avec 5 ou 6 et lorsque Console.WriteLine
appelle ToString()
, le nom de e1
est résolu tandis que le nom de e2
ne l'est pas.
si ce n'est pas ce que vous vouliez, utilisez Enum.IsDefined(typeof(MyEnum), 6)
pour vérifier si la valeur que vous utilisez correspond à un enum défini.
notez aussi que je suis explicite sur le type sous-jacent de l'enum, même si le compilateur le vérifie. Je fais ça pour m'assurer de ne pas tomber dans des surprises. Pour voir ces surprises en action, vous pouvez utiliser le code suivant (en fait, j'ai vu ce qui se passe beaucoup dans le code de la base de données)):
public enum MyEnum : short
{
Mek = 5
}
static void Main(string[] args)
{
var e1 = (MyEnum)32769; // will not compile, out of bounds for a short
object o = 5;
var e2 = (MyEnum)o; // will throw at runtime, because o is of type int
Console.WriteLine("{0} {1}", e1, e2);
Console.ReadLine();
}
prendre l'exemple suivant:
int one = 1;
MyEnum e = (MyEnum)one;
j'utilise ce morceau de code pour lancer int à mon enum:
if (typeof(YourEnum).IsEnumDefined(valueToCast)) return (YourEnum)valueToCast;
else { //handle it here, if its not defined }
je trouve que c'est la meilleure solution.
ci-dessous est une classe d'utilité nice pour Enums
public static class EnumHelper
{
public static int[] ToIntArray<T>(T[] value)
{
int[] result = new int[value.Length];
for (int i = 0; i < value.Length; i++)
result[i] = Convert.ToInt32(value[i]);
return result;
}
public static T[] FromIntArray<T>(int[] value)
{
T[] result = new T[value.Length];
for (int i = 0; i < value.Length; i++)
result[i] = (T)Enum.ToObject(typeof(T),value[i]);
return result;
}
internal static T Parse<T>(string value, T defaultValue)
{
if (Enum.IsDefined(typeof(T), value))
return (T) Enum.Parse(typeof (T), value);
int num;
if(int.TryParse(value,out num))
{
if (Enum.IsDefined(typeof(T), num))
return (T)Enum.ToObject(typeof(T), num);
}
return defaultValue;
}
}
si vous êtes prêt pour le 4.0 .NET Framework, Il ya un nouveau Enum.TryParse () fonction qui est très utile et qui joue bien avec l'attribut [Flags]. Voir Enum.Méthode TryParse (String, TEnum)%)
pour les valeurs numériques, c'est plus sûr car il retournera un objet quoi qu'il arrive:
public static class EnumEx
{
static public bool TryConvert<T>(int value, out T result)
{
result = default(T);
bool success = Enum.IsDefined(typeof(T), value);
if (success)
{
result = (T)Enum.ToObject(typeof(T), value);
}
return success;
}
}
si vous avez un entier qui agit comme un masque de bits et pourrait représenter une ou plusieurs valeurs dans une énumération [Flags], vous pouvez utiliser ce code pour séparer les valeurs de chaque drapeau dans une liste:
for (var flagIterator = 0x1; flagIterator <= 0x80000000; flagIterator <<= 1)
{
// Check to see if the current flag exists in the bit mask
if ((intValue & flagIterator) != 0)
{
// If the current flag exists in the enumeration, then we can add that value to the list
// if the enumeration has that flag defined
if (Enum.IsDefined(typeof(MyEnum), flagIterator))
ListOfEnumValues.Add((MyEnum)flagIterator);
}
}
parfois, vous avez un objet du type MyEnum
. Comme
var MyEnumType = typeof(MyEnumType);
puis:
Enum.ToObject(typeof(MyEnum), 3)
il s'agit d'une méthode de conversion sûre tenant compte de l'énumération des drapeaux:
public static bool TryConvertToEnum<T>(this int instance, out T result)
where T: struct
{
var enumType = typeof (T);
if (!enumType.IsEnum)
{
throw new ArgumentException("The generic type must be an enum.");
}
var success = Enum.IsDefined(enumType, instance);
if (success)
{
result = (T)Enum.ToObject(enumType, instance);
}
else
{
result = default(T);
}
return success;
}
pour convertir une chaîne en enum ou int en constante ENUM, nous devons utiliser Enum.Fonction d'analyse. Voici une vidéo youtube https://www.youtube.com/watch?v=4nhx4VwdRDk qui montrent réellement avec la chaîne et la même chose s'applique pour int.
le code va comme montré ci-dessous où" rouge "est la chaîne et" MyColors " est l'ÉNUM de couleur qui a les constantes de couleur.
MyColors EnumColors = (MyColors)Enum.Parse(typeof(MyColors), "Red");
s'éloignant légèrement de la question originale, mais j'ai trouvé une réponse à la question de débordement de pile obtenir la valeur int de enum utile. Créez une classe statique avec les propriétés public const int
, vous permettant de rassembler facilement un tas de constantes int
liées, et ensuite ne pas avoir à les mouler à int
en les utilisant.
public static class Question
{
public static readonly int Role = 2;
public static readonly int ProjectFunding = 3;
public static readonly int TotalEmployee = 4;
public static readonly int NumberOfServers = 5;
public static readonly int TopBusinessConcern = 6;
}
évidemment, certaines fonctionnalités du type enum seront perdu, mais pour stocker un tas de constantes d'id de base de données, il semble comme une solution assez ordonnée.
ce parses entiers ou Chaînes à un enum cible avec correspondance partielle dans dot.NET 4.0 utiliser des génériques comme dans la classe d'utilité de Tawani ci-dessus. Je l'utilise pour convertir les variables de commutateur de ligne de commande qui peuvent être incomplètes. Puisqu'un enum ne peut pas être null, vous devriez logiquement fournir une valeur par défaut. On peut l'appeler ainsi:
var result = EnumParser<MyEnum>.Parse(valueToParse, MyEnum.FirstValue);
voici le code:
using System;
public class EnumParser<T> where T : struct
{
public static T Parse(int toParse, T defaultVal)
{
return Parse(toParse + "", defaultVal);
}
public static T Parse(string toParse, T defaultVal)
{
T enumVal = defaultVal;
if (defaultVal is Enum && !String.IsNullOrEmpty(toParse))
{
int index;
if (int.TryParse(toParse, out index))
{
Enum.TryParse(index + "", out enumVal);
}
else
{
if (!Enum.TryParse<T>(toParse + "", true, out enumVal))
{
MatchPartialName(toParse, ref enumVal);
}
}
}
return enumVal;
}
public static void MatchPartialName(string toParse, ref T enumVal)
{
foreach (string member in enumVal.GetType().GetEnumNames())
{
if (member.ToLower().Contains(toParse.ToLower()))
{
if (Enum.TryParse<T>(member + "", out enumVal))
{
break;
}
}
}
}
}
pour information: la question portait sur les entiers, que personne n'a mentionnés seront aussi explicitement convertis en Enum.TryParse ()
à Partir d'une chaîne: (Enum.L'analyse est périmée, utilisez Enum.TryParse)
enum Importance
{}
Importance importance;
if (Enum.TryParse(value, out importance))
{
}
ci-dessous est légèrement meilleure méthode d'extension
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;
}
dans mon cas, je devais rendre l'enum d'un service de la WCF. J'avais aussi besoin d'un nom Amical, pas seulement l'enum.ToString ().
voici ma classe WCF.
[DataContract]
public class EnumMember
{
[DataMember]
public string Description { get; set; }
[DataMember]
public int Value { get; set; }
public static List<EnumMember> ConvertToList<T>()
{
Type type = typeof(T);
if (!type.IsEnum)
{
throw new ArgumentException("T must be of type enumeration.");
}
var members = new List<EnumMember>();
foreach (string item in System.Enum.GetNames(type))
{
var enumType = System.Enum.Parse(type, item);
members.Add(
new EnumMember() { Description = enumType.GetDescriptionValue(), Value = ((IConvertible)enumType).ToInt32(null) });
}
return members;
}
}
Voici la méthode D'Extension qui obtient la Description de L'Enum.
public static string GetDescriptionValue<T>(this T source)
{
FieldInfo fileInfo = source.GetType().GetField(source.ToString());
DescriptionAttribute[] attributes = (DescriptionAttribute[])fileInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);
if (attributes != null && attributes.Length > 0)
{
return attributes[0].Description;
}
else
{
return source.ToString();
}
}
mise en Œuvre:
return EnumMember.ConvertToList<YourType>();
Différentes manières de fonte et de Enum
enum orientation : byte
{
north = 1,
south = 2,
east = 3,
west = 4
}
class Program
{
static void Main(string[] args)
{
orientation myDirection = orientation.north;
Console.WriteLine(“myDirection = {0}”, myDirection); //output myDirection =north
Console.WriteLine((byte)myDirection); //output 1
string strDir = Convert.ToString(myDirection);
Console.WriteLine(strDir); //output north
string myString = “north”; //to convert string to Enum
myDirection = (orientation)Enum.Parse(typeof(orientation),myString);
}
}
Je ne sais plus où je trouve la partie de cette extension enum, mais elle vient de stackoverflow. Je suis désolé pour cette! Mais j'ai pris celui-ci et je l'ai modifié pour des énums avec des drapeaux. Pour les énums avec des drapeaux j'ai fait ceci:
public static class Enum<T> where T : struct
{
private static readonly IEnumerable<T> All = Enum.GetValues(typeof (T)).Cast<T>();
private static readonly Dictionary<int, T> Values = All.ToDictionary(k => Convert.ToInt32(k));
public static T? CastOrNull(int value)
{
T foundValue;
if (Values.TryGetValue(value, out foundValue))
{
return foundValue;
}
// For enums with Flags-Attribut.
try
{
bool isFlag = typeof(T).GetCustomAttributes(typeof(FlagsAttribute), false).Length > 0;
if (isFlag)
{
int existingIntValue = 0;
foreach (T t in Enum.GetValues(typeof(T)))
{
if ((value & Convert.ToInt32(t)) > 0)
{
existingIntValue |= Convert.ToInt32(t);
}
}
if (existingIntValue == 0)
{
return null;
}
return (T)(Enum.Parse(typeof(T), existingIntValue.ToString(), true));
}
}
catch (Exception)
{
return null;
}
return null;
}
}
exemple:
[Flags]
public enum PetType
{
None = 0, Dog = 1, Cat = 2, Fish = 4, Bird = 8, Reptile = 16, Other = 32
};
integer values
1=Dog;
13= Dog | Fish | Bird;
96= Other;
128= Null;
il peut vous aider à convertir n'importe quelles données d'entrée à l'utilisateur désiré enum . Supposons que vous ayez un enum comme ci-dessous qui par défaut int . Veuillez ajouter une valeur par défaut au début de votre enum. Qui est utilisé chez helpers medthod quand il n'y a pas de correspondance trouvée avec la valeur d'entrée.
public enum FriendType
{
Default,
Audio,
Video,
Image
}
public static class EnumHelper<T>
{
public static T ConvertToEnum(dynamic value)
{
var result = default(T);
var tempType = 0;
//see Note below
if (value != null &&
int.TryParse(value.ToString(), out tempType) &&
Enum.IsDefined(typeof(T), tempType))
{
result = (T)Enum.ToObject(typeof(T), tempType);
}
return result;
}
}
N. B: ici, j'essaie de décomposer la valeur en int, car enum est par défaut int Si vous définissez enum comme ceci qui est byte type.
public enum MediaType : byte
{
Default,
Audio,
Video,
Image
}
vous devez changer l'analyse à la méthode helper de
int.TryParse(value.ToString(), out tempType)
à
byte.TryParse(value.ToString(), out tempType)
je vérifie ma méthode pour les entrées suivantes
EnumHelper<FriendType>.ConvertToEnum(null);
EnumHelper<FriendType>.ConvertToEnum("");
EnumHelper<FriendType>.ConvertToEnum("-1");
EnumHelper<FriendType>.ConvertToEnum("6");
EnumHelper<FriendType>.ConvertToEnum("");
EnumHelper<FriendType>.ConvertToEnum("2");
EnumHelper<FriendType>.ConvertToEnum(-1);
EnumHelper<FriendType>.ConvertToEnum(0);
EnumHelper<FriendType>.ConvertToEnum(1);
EnumHelper<FriendType>.ConvertToEnum(9);
désolé pour mon anglais