Получить значение int из enum в C #

1827

У меня есть класс под названием Questions(множественное число). В этом классе есть перечисление Question(единственное), которое выглядит следующим образом.

public enum Question
{
    Role = 2,
    ProjectFunding = 3,
    TotalEmployee = 4,
    NumberOfServers = 5,
    TopBusinessConcern = 6
}

В Questionsклассе у меня есть get(int foo)функция, которая возвращает Questionsобъект для этого foo. Есть ли простой способ получить целочисленное значение из перечисления, чтобы я мог сделать что-то вроде этого Questions.Get(Question.Role)?

Джим
источник
11
Я знаю, что опаздываю на вечеринку, но вместо того, чтобы определить свой метод, как get(int foo)вы можете определить его, а get(Question foo)затем выполнить кастинг внутри метода, вы можете вызвать свой метод какQuestions.Get(Question.Role)
Joe

Ответы:

2356

Просто приведите перечисление, например

int something = (int) Question.Role;

Вышеприведенное будет работать для подавляющего большинства перечислений, которые вы видите в дикой природе, так как базовый тип по умолчанию для перечисления это int.

Однако, как отмечает Сесилфиллип , перечисления могут иметь разные базовые типы. Если перечисление объявляется как uint, longили ulong, он должен быть приведен к типу перечисления; например для

enum StarsInMilkyWay:long {Sun = 1, V645Centauri = 2 .. Wolf424B = 2147483649};

ты должен использовать

long something = (long)StarsInMilkyWay.Wolf424B;
тетранейтрона
источник
23
@ Гарри, это не правда. Вы можете создать Перечисление без приведения, это не обязательно. и я назначаю номер только в особых случаях, большую часть времени оставляю как значение по умолчанию. но вы можете сделать enum Test { Item = 1 }и увидеть, что 1 == (int)Test.Itemэто равно.
Jaider
33
@ Jaider (int)Test.ItemЭто актерский состав! () является явным оператором приведения.
Синтия V
48
@Sinthia V он сказал, что вы можете создать его без кастинга, что правильно
Пол Риджуэй
7
Если базовый тип для enum Questionне был, intно longэто приведение будет усекать Roleинтегральное значение!
Quaylar
1
Когда вы принимаете Enumв качестве параметра, вы знаете, что вы можете получить только фиксированное количество возможных интегральных значений. С другой стороны, если вы просто берете an int, то вам нужно проверить, intнаходится ли это в пределах допустимых значений, что усложнит код. Вы всегда можете переопределить свои подписи как `` `public void MyMethod (int x) {// сделать что-то с x} public void MyMethod (Enum x) {this.MyMethod ((int) x); } `` ``
percebus
307

Так как Перечисления могут быть любым интегральным типом ( byte, int, shortи т.д.), более надежный способ получить лежащее в основе интегрального значения перечисления было бы сделать использование GetTypeCodeметода в сочетании с Convertклассом:

enum Sides {
    Left, Right, Top, Bottom
}
Sides side = Sides.Bottom;

object val = Convert.ChangeType(side, side.GetTypeCode());
Console.WriteLine(val);

Это должно работать независимо от базового целочисленного типа.

cecilphillip
источник
32
Этот метод доказал свою ценность для меня при работе с универсальным типом, где T: enum (на самом деле T: struct, IConvertible, но это другая история).
aboy021
1
Как бы вы изменили это, чтобы распечатать шестнадцатеричное значение стороны? Этот пример показывает десятичное значение. Проблема в том, что varэто тип object, поэтому вам нужно распаковать его, и он станет более грязным, чем мне бы хотелось.
Марк Лаката
2
Я думаю , вы должны изменить пример в вашем примере будет всегда . object val = Convert...etcvarobject
Сетка
2
@TimAbell Все, что я могу действительно сказать, - это то, что мы обнаружили, что динамически скомпилированные страницы aspx (где вы должны развернуть файлы .cs на работающем сервере) назначали целые числа по-разному для каждого значения. Это означало, что сериализованные объекты на одной машине, десериализовались с разными значениями на другой машине и эффективно повреждались (вызывая часы путаницы). Мы подняли его с помощью MS, и я, кажется, вспоминаю, что они сказали, что автоматически сгенерированные целые числа не были одинаковыми при сборке в разных версиях фреймворка.
NickG
4
@TimAbell В отдельном случае разработчик удалил устаревшее / неиспользуемое значение Enum, в результате чего все остальные значения в последовательности вышли на единицу. Таким образом, наши стандарты кодирования теперь требуют, чтобы идентификаторы всегда указывались явно, в противном случае добавление / удаление или даже автоматическое форматирование кода (например, сортировка по алфавиту) изменит все значения, вызывающие повреждение данных. Я настоятельно рекомендую всем указывать все целые числа Enum явно. Это очень важно, если они соотносятся с внешними (база данных) сохраненными значениями.
NickG
199

Объявите его как статический класс, имеющий открытые константы:

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;
}

И тогда вы можете ссылаться на него как Question.Role, и он всегда оценивается как intили как вы его определяете.

PablosBicicleta
источник
31
Я бы использовал, static readonly intпотому что константы скомпилированы в их жесткие значения. См. Stackoverflow.com/a/755693/492
CAD Bloke
96
Это решение на самом деле не дает реальной выгоды от строго типизированных перечислений. Если бы я только хотел передать GameState-enum-параметр конкретному методу, например, компилятор не должен позволять мне передавать какую-либо переменную типа int в качестве параметра.
THGC
12
@CADBloke, именно поэтому вы будете использовать, constа не static readonlyпотому, что каждый раз, когда вы сравниваете, static readonlyвы вызываете метод, чтобы получить значение переменной, тогда как constвы сравниваете два типа значений напрямую.
blockloop
3
@ brettof86 Да, const будет быстрее, если ограничение компиляции никогда не будет проблемой, тогда все хорошо.
САПР bloke
2
@ Зак Я не очень хорошо объяснил это, compilation limitationимея в виду, что значение жестко закодировано, когда вы его компилируете, поэтому любое изменение этого значения потребует перекомпиляции всех сборок, использующих его. Я склонен согласиться с вами по поводу использования, потому что изменение значений будет иметь далеко идущие последствия.
CAD bloke
87
Question question = Question.Role;
int value = (int) question;

Приведет к value == 2.

jerryjvl
источник
34
Вопрос о временной переменной не нужен.
Гишу
1
Так что-то вроде этого Questions.Get (Convert.ToInt16 (Question.Applications))
Джим
6
Вы можете просто разыграть в любом направлении; Единственное, на что нужно обратить внимание, это на то, что перечисления ничего не приводят в исполнение (значение перечисления может быть 288, даже если с таким числом не существует Вопроса)
Марк Гравелл
@jim: Нет, просто приведите значение: Questions.Get ((int) Question.Applications);
Гуффа
1
@Gishu Можно сказать, что это ... сомнительно. ;)
Феликс Д.
79

С другой стороны, если вы хотите получить intзначение System.Enum, то укажите eздесь:

Enum e = Question.Role;

Ты можешь использовать:

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);

Последние два просто безобразны. Я предпочитаю первый.

Навфал
источник
1
Второй самый быстрый, хотя.
Йохан Б
1
Как тот, кто привык использовать Mixins в моддинге Minecraft, второй кажется очевидным победителем.
Sollace
40

Это проще, чем вы думаете - перечисление уже int. Это просто нужно напомнить:

int y = (int)Question.Role;
Console.WriteLine(y); // Prints 2
Майкл Петротта
источник
15
Nitpick: это перечисление уже int. Другие перечисления могут быть разных типов - попробуйте "enum SmallEnum: byte {A, B, C}"
mqp
9
Абсолютная правда. Ссылка C #: «Каждый тип перечисления имеет базовый тип, который может быть любым целым типом, кроме char».
Майкл Петротта
33

Пример:

public Enum EmpNo
{
    Raj = 1,
    Rahul,
    Priyanka
}

И в коде, чтобы получить значение enum:

int setempNo = (int)EmpNo.Raj; // This will give setempNo = 1

или

int setempNo = (int)EmpNo.Rahul; // This will give setempNo = 2

Перечисления будут увеличиваться на 1, и вы можете установить начальное значение. Если вы не установите начальное значение, оно будет изначально присвоено как 0.

Питер Мортенсен
источник
6
Это на самом деле компилируется?
Питер Мортенсен
Может ли что-то, что является Раджем, также быть Рахулом или Приянкой? Ваши ценности конфликтуют и должны удваиваться, чтобы быть уникальными, например, 0, 1, 2, 4, 8 и т. Д. Это моя основная проблема с перечислениями.
Тимоти Гонсалес
@TimothyGonzalez на самом деле перечисления просто считают до 1, если вы явно не указали их значение;)
derHugo
@derHugo, это зависит от того, что вы предполагаете, что числовые значения равны основанию 10 или основанию 2.
Тимоти Гонсалес,
@TimothyGonzalez ну там не так много , чтобы предположить ... Я просто указал, что по умолчанию они просто подсчитывают 1в intкроме вас явно определить иначе
derHugo
28

Недавно я перешел от использования перечислений в моем коде в пользу использования классов с защищенными конструкторами и предопределенными статическими экземплярами (благодаря Roelof - C # Enure Valid Enum Values ​​- Futureproof Method) ).

В свете этого, ниже, как я теперь подхожу к этой проблеме (включая неявное преобразование в / из 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)
}

Преимущество этого подхода состоит в том, что вы получаете все, что у вас было бы из перечисления, но ваш код теперь гораздо более гибок, поэтому, если вам нужно выполнять различные действия, основанные на значении Question, вы можете поместить логику в Questionсебя (то есть в предпочтительный ОО) fashion) вместо того, чтобы помещать в ваш код множество операторов case для решения каждого сценария.


NB: Ответ обновлен 2018-04-27, чтобы использовать функции C # 6; т.е. выражения объявления и определения тела лямбда-выражения. Смотрите историю изменений для оригинального кода. Это дает преимущество, делая определение немного менее многословным; которая была одной из основных жалоб на подход этого ответа.

JohnLBevan
источник
2
Я предполагаю, что это компромисс между явным приведением и кодом, который вы должны написать, чтобы обойти его. Все еще люблю реализацию, просто жаль, что это не было так долго. +1
Lankymart
3
Я использовал несколько различных типов классов, структурированных аналогично этому. Я нахожу, что они творят чудеса, пытаясь следовать методологии «не дай мне быть идиотом позже».
Джеймс Хауг
20

Если вы хотите получить целое число для значения enum, которое хранится в переменной, тип которой будет Questionиспользоваться, например, в методе, вы можете просто сделать это, как я написал в этом примере:

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();
}

Это изменит заголовок окна на 4, так как переменная Geselecteerdявляется Talen.Nederlands. Если я изменю его на Talen.Portugeesи вызову метод снова, текст изменится на 3.

Матейс ван дер Слагт
источник
3
кодирование на голландском. о, Боже.
WiseStrawberry
К сожалению, этот подход дает плохую производительность, чем больше вы используете его. Я попробовал это в своем коде, и с течением времени мое приложение становилось все медленнее и медленнее, с все меньшим использованием процессора. Это подразумевало, что потоки чего-то ожидали - я предполагаю какую-то сборку мусора, возможно, из-за помещения параметра enum в ToInt32 (). Переключившись на простой int.Parse (), я смог полностью устранить эту низкую производительность, и производительность осталась прежней, независимо от того, как долго выполнялся код.
Грег
16

Чтобы убедиться, что значение enum существует, а затем проанализировать его, вы также можете сделать следующее.

// 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() + ".");
Nathon
источник
14

Может быть, я пропустил это, но кто-нибудь пробовал простой общий метод расширения?

Это прекрасно работает для меня. Таким способом вы можете избежать приведения типов в вашем API, но в конечном итоге это приведет к операции изменения типа. Это хороший случай для программирования Roslyn, чтобы компилятор сделал метод GetValue <T> для вас.

    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;
    }
}
Doug
источник
Возможно, потому что выполнение (int) customFlag меньше набирает текст и делает более или менее одно и то же?
Тим Китинг
Re "Может быть, я пропустил это, но кто-нибудь пробовал простой общий метод расширения ?" : SixOThree сказал : « Вместо этого используйте метод расширения » и Бронек сказал: «Вы можете сделать это, внедрив метод расширения в определенный вами тип перечисления» .
Питер Мортенсен
13

Еще один способ сделать это:

Console.WriteLine("Name: {0}, Value: {0:D}", Question.Role);

Это приведет к:

Name: Role, Value: 2
plavozont
источник
12
public enum QuestionType
{
    Role = 2,
    ProjectFunding = 3,
    TotalEmployee = 4,
    NumberOfServers = 5,
    TopBusinessConcern = 6
}

... это хорошая декларация.

Вы должны привести результат к int следующим образом:

int Question = (int)QuestionType.Role

В противном случае тип по-прежнему QuestionType .

Этот уровень строгости является способом C #.

Одна альтернатива - вместо этого использовать объявление класса:

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
}

Это менее элегантно для объявления, но вам не нужно приводить его в коде:

int Question = QuestionType.Role

Кроме того, вы можете чувствовать себя более комфортно с Visual Basic, который обслуживает такого рода ожидания во многих областях.

Чудотворец
источник
11
int number = Question.Role.GetHashCode();

numberдолжен иметь значение 2.

JaimeArmenta
источник
GetHashCode - это один из способов получить значение из общей маски Enum
ThanhLD,
Обратите внимание , что это только «законным» для bool*, byte, ushort, int, и uint**. GetHashCode для других типов изменяет значение, например, выполняет некоторые битовые смещения и xors. (* 1/0, ** приведено к int, конечно). Но в общем, просто не делайте этого, если это не ваш личный код.
AnorZaken
10

Вы можете сделать это, реализовав метод расширения для вашего определенного типа перечисления:

public static class MyExtensions
{
    public static int getNumberValue(this Question questionThis)
    {
        return (int)questionThis;
    }
}

Это упрощает получение значения int текущего значения перечисления:

Question question = Question.Role;
int value = question.getNumberValue();

или

int value = Question.Role.getNumberValue();
Бронек
источник
5
Бронек, то, что вы сделали, это создали неинформативный синтаксис с помощью метода расширения (не универсального, кстати), который на самом деле занимает больше времени для записи. Я не вижу, как это лучше, чем оригинальное решение от Tetraneutron. Давайте не будем превращать это в чат, помощь всегда приветствуется в stackoverflow, и все здесь, чтобы помочь. Пожалуйста, примите мой комментарий как конструктивную критику.
Бенджамин Грюнбаум
2
Бенджамин, во-первых, почему ты удалил мой комментарий? Я не понимаю твоих решений - может быть, кто-то другой в сообществе согласится с моим комментарием. Во-вторых, мое решение обернуло одно Tetraneutron, и оно точно и легче, и меньше написано, потому что IntelliSense предлагает метод расширения. Поэтому я думаю, что ваше решение не является беспристрастным и репрезентативным. Я вижу много аналогичных ответов по стеку, и это нормально. В любом случае, я использую свое решение, и, возможно, некоторые люди выберут мое решение в будущем, но эти негативные моменты затрудняют поиск. Больше всего это правильно, а не копировать.
Бронек
3
@Bronek Если вы не пингуете меня, у меня нет никаких признаков того, что вы ответили. Я не удалил ваш комментарий, у меня нет возможности или хочу сделать это. Скорее всего, мод пришел и удалил его - вы можете отметить его для внимания модератора и спросить почему или еще лучше - спросите о переполнении стека мета . У меня есть мнение о вашем решении с точки зрения программирования, которое совершенно по моему праву - для этого и нужны комментарии, не нужно воспринимать его как личный.
Бенджамин Грюнбаум
8

Вместо этого используйте метод расширения:

public static class ExtensionMethods
{
    public static int IntValue(this Enum argEnum)
    {
        return Convert.ToInt32(argEnum);
    }
}

И использование немного красивее:

var intValue = Question.Role.IntValue();
SixOThree
источник
7
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 a 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);
}
Gauravsa
источник
масть - «10. (карточные игры). Каждый из наборов колоды карт различается по цвету и / или определенным эмблемам, таким как пики, сердца, алмазы или трефы традиционных англо-испаноязычных и французских игральных карт».
Питер Мортенсен
Объяснение примера кода будет в порядке ( отредактировав свой ответ , а не здесь, в комментариях).
Питер Мортенсен
Ноль, как правило, зарезервирован для состояния unset / unkown в перечислениях, необычно определять его таким образом
Чад Грант,
6

Использование:

Question question = Question.Role;
int value = question.GetHashCode();

Это приведет value == 2.

Это верно только в том случае, если перечисление помещается внутрь int.

GinCanhViet
источник
1
Это верно только в том случае, если enum помещается внутри, intконечно, так как GetHashCodeвозвращает целое число.
РБ.
5

Поскольку перечисления могут быть объявлены с несколькими примитивными типами, может быть полезен универсальный метод расширения для приведения любого типа перечисления.

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;
Джеффри Феррейрас
источник
4

Ниже приводится метод расширения

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;
}
Камран Шахид
источник
4

Мой любимый хак с int или меньшими перечислениями:

GetHashCode();

Для перечисления

public enum Test
{
    Min = Int32.MinValue,
    One = 1,
    Max = Int32.MaxValue,
}

Эта,

var values = Enum.GetValues(typeof(Test));

foreach (var val in values)
{
    Console.WriteLine(val.GetHashCode());
    Console.WriteLine(((int)val));
    Console.WriteLine(val);
}

выходы

one
1
1
max
2147483647
2147483647
min
-2147483648
-2147483648

Отказ от ответственности:

Это не работает для перечислений, основанных на долго.

Эрик Карлссон
источник
3

Самым простым решением, которое я могу придумать, является перегрузка Get(int)метода следующим образом:

[modifiers] Questions Get(Question q)
{
    return Get((int)q);
}

где [modifiers]обычно может быть таким же, как для Get(int)метода. Если вы не можете редактировать Questionsкласс или по какой-то причине этого не хотите, вы можете перегрузить метод, написав расширение:

public static class Extensions
{
    public static Questions Get(this Questions qs, Question q)
    {
        return qs.Get((int)q);
    }
}
Grx70
источник
3

Пример, который я хотел бы предложить «получить значение int из перечисления», это

public enum Sample
{
    Book = 1, 
    Pen = 2, 
    Pencil = 3
}

int answer = (int)Sample.Book;

Теперь ответ будет 1.

Вивек
источник
3

Использование:

Question question = Question.Role;
int value = Convert.ToInt32(question);
Питер Мортенсен
источник
2

Попробуйте это вместо преобразования enum в int:

public static class ReturnType
{
    public static readonly int Success = 1;
    public static readonly int Duplicate = 2;
    public static readonly int Error = -1;        
}
Налан Мадхесваран
источник
2

В Visual Basic это должно быть:

Public Enum Question
    Role = 2
    ProjectFunding = 3
    TotalEmployee = 4
    NumberOfServers = 5
    TopBusinessConcern = 6
End Enum

Private value As Integer = CInt(Question.Role)
VPP
источник
3
Вопрос к C #.
Ctrl S
2
В заголовке написано «Получить значение int из enum в C #» .
Питер Мортенсен
0

Я придумал этот метод расширения, который включает в себя текущие функции языка. Используя динамический, мне не нужно делать это универсальным методом и указывать тип, который делает вызов более простым и последовательным:

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;
    }
Джефф
источник
пожалуйста, нет, вы можете сделать все это в одной строке Convert.Changetype (e, e.GetTypeCode ()) и получить объект обратно, без необходимости в динамике или методе расширения
Чад Грант
Я не согласен с использованием Convert. Просто использовать актерский состав будет проще. Мое намерение состояло в том, чтобы иметь возможность преобразовать любое перечисление в его значение без использования приведения. Это позволяет изменять тип enum без необходимости изменения всех связанных приведений - но когда это происходит? Метод расширения работает правильно. Тем не менее, у меня есть проблема с этим в том, что, поскольку он динамический, компилятор не может проверить тип (очевидно, для всего оператора), что означает, что проверка типа происходит при запуске - не хорошее решение. Я думаю, что я вернусь к броскам.
Джефф
1
Я не говорил использовать его вместо приведения, просто этот код бессмысленный и ничего не выполняет, на самом деле усугубляет проблему. Я бы порекомендовал удалить это решение
Чад Грант