Я хотел бы создать общий метод для преобразования любого производного типа System.Enum в соответствующее ему целочисленное значение без преобразования типов и, желательно, без анализа строки.
Например, я хочу примерно следующее:
// Trivial example, not actually what I'm doing.
class Converter
{
int ToInteger(System.Enum anEnum)
{
(int)anEnum;
}
}
Но это, похоже, не работает. Resharper сообщает, что вы не можете привести выражение типа System.Enum к типу int.
Теперь я придумал это решение, но я бы предпочел что-то более эффективное.
class Converter
{
int ToInteger(System.Enum anEnum)
{
return int.Parse(anEnum.ToString("d"));
}
}
Какие-либо предложения?
Ответы:
Если ты не хочешь кастовать,
может сделать свое дело.
Прямая трансляция (через
(int)enumValue
) невозможна. Обратите внимание , что это также будет «опасным» , поскольку перечисление может иметь различные типы , лежащие в основе (int
,long
,byte
...).Более формально:
System.Enum
не имеет прямого отношения наследования сInt32
(хотя оба являютсяValueType
s), поэтому явное приведение не может быть правильным в системе типовисточник
Converter.ToInteger(MyEnum.MyEnumConstant);
здесь не будет ошибок. Пожалуйста, отредактируйте эту часть.int
long
enum.System.Enum
- это класс, поэтому это ссылочный тип. Значения, вероятно, заключены в рамку.Я заставил его работать, приведя к объекту, а затем к int:
public static class EnumExtensions { public static int ToInt(this Enum enumValue) { return (int)((object)enumValue); } }
Это уродливый и, наверное, не лучший способ. Я буду продолжать возиться с этим, чтобы посмотреть, смогу ли я придумать что-нибудь получше ...
РЕДАКТИРОВАТЬ: как раз собирался опубликовать, что Convert.ToInt32 (enumValue) также работает, и заметил, что MartinStettner превзошел меня в этом.
public static class EnumExtensions { public static int ToInt(this Enum enumValue) { return Convert.ToInt32(enumValue); } }
Контрольная работа:
int x = DayOfWeek.Friday.ToInt(); Console.WriteLine(x); // results in 5 which is int value of Friday
РЕДАКТИРОВАТЬ 2: В комментариях кто-то сказал, что это работает только в С # 3.0. Я только что протестировал это в VS2005, и это сработало:
public static class Helpers { public static int ToInt(Enum enumValue) { return Convert.ToInt32(enumValue); } } static void Main(string[] args) { Console.WriteLine(Helpers.ToInt(DayOfWeek.Friday)); }
источник
Если вам нужно преобразовать любое перечисление в его базовый тип (не все перечисления поддерживаются
int
), вы можете использовать:return System.Convert.ChangeType( enumValue, Enum.GetUnderlyingType(enumValue.GetType()));
источник
Convert.ChangeType
принимаетobject
в качестве первого аргумента и возвращаетobject
.Зачем нужно изобретать велосипед с помощью вспомогательного метода? Совершенно законно использовать
enum
значение к его базовому типу.Он меньше печатает и, на мой взгляд, более читабелен ...
int x = (int)DayOfWeek.Tuesday;
... а не что-то вроде ...
int y = Converter.ToInteger(DayOfWeek.Tuesday); // or int z = DayOfWeek.Tuesday.ToInteger();
источник
Из моего ответа здесь :
Дано
e
как в:Тогда работают такие:
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);
Последние два уродливые. Первый должен быть более читабельным, хотя второй намного быстрее. Или может быть метод расширения является лучшим, лучшим из обоих миров.
public static int GetIntValue(this Enum e) { return e.GetValue<int>(); } public static T GetValue<T>(this Enum e) where T : struct, IComparable, IFormattable, IConvertible, IComparable<T>, IEquatable<T> { return (T)(object)e; }
Теперь вы можете позвонить:
e.GetValue<int>(); //or e.GetIntValue();
источник
e
переменная уже имеет упакованный экземпляр фактического типа значения, то есть enum. Когда пишешьEnum e = Question.Role;
, уже в коробке. Вопрос в том, чтобы преобразовать коробкуSystem.Enum
обратно в базовый тип int (распаковка). Итак, распаковка - это только проблема производительности.(int)(object)e
прямой вызов распаковки; да должно быть быстрее, чем другие подходы. Смотрите этоПриведение из a
System.Enum
в aint
отлично работает для меня (это также есть в MSDN ). Возможно, это ошибка Resharper.источник
System.Enum
, а неSystem.Enum
себя.Поскольку перечисления ограничены байтами, sbyte, short, ushort, int, uint, long и ulong, мы можем сделать некоторые предположения.
Мы можем избежать исключений во время преобразования, используя самый большой доступный контейнер. К сожалению, неясно, какой контейнер использовать, потому что ulong взорвется для отрицательных чисел, а long - для чисел между long.MaxValue и ulong.MaxValue. Нам нужно переключаться между этими вариантами в зависимости от базового типа.
Конечно, вам все равно нужно решить, что делать, если результат не помещается в int. Я думаю, что кастинг - это нормально, но все же есть некоторые подводные камни:
Вот мое предложение, оставляю читателю решать, где раскрыть эту функцию; как помощник или расширение.
public int ToInt(Enum e) { unchecked { if (e.GetTypeCode() == TypeCode.UInt64) return (int)Convert.ToUInt64(e); else return (int)Convert.ToInt64(e); } }
источник
Не забывайте, что в самом типе Enum есть множество статических вспомогательных функций. Если все, что вам нужно сделать, это преобразовать экземпляр перечисления в соответствующий ему целочисленный тип, то приведение типов, вероятно, является наиболее эффективным способом.
Я думаю, что ReSharper жалуется, потому что Enum не является перечислением какого-либо конкретного типа, а сами перечисления являются производными от скалярного типа значений, а не Enum. Если вам нужно универсальное адаптируемое приведение, я бы сказал, что это может вам подойти (обратите внимание, что сам тип перечисления также включен в общий:
public static EnumHelpers { public static T Convert<T, E>(E enumValue) { return (T)enumValue; } }
Затем это можно было бы использовать так:
public enum StopLight: int { Red = 1, Yellow = 2, Green = 3 } // ... int myStoplightColor = EnumHelpers.Convert<int, StopLight>(StopLight.Red);
Я не могу сказать наверняка, но приведенный выше код может даже поддерживаться выводом типа C #, позволяя следующее:
int myStoplightColor = EnumHelpers.Convert<int>(StopLight.Red);
источник
EnumHelpers.Convert<int, StopLight>(StopLight.Red);
вместо(int)StopLight.Read;
? Также идет речь о томSystem.Enum
.