Зачем нам нужно вводить листинг enum в С#

У меня есть перечисление вроде:

public enum Test:int
{
   A=1, 
   B=2
}

Итак, здесь я знаю, что мой enum - это тип int, но если я хочу сделать что-то вроде следующего:

int a = Test.A;

это не работает.

Если у меня есть класс вроде:

public class MyTest
{
    public static int A =1;
}

Могу сказать,

int a = MyTest.A;

Здесь мне не нужно явно выделять A в int.

Ответ 1

С обновленным примером:

public class MyTest
{
    public static int A =1;
}

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

int a = MyTest.A;

Это не то, как выглядят перечисления. Enums больше похожи (комментарии - это места, где мы отличаемся от реального перечисления):

public struct MyTest /* Of course, this isn't correct, because we'll inherit from System.ValueType. An enum should inherit from System.Enum */
{
    private int _value; /* Should be marked to be treated specially */
    private MyTest(int value) /* Doesn't need to exist, since there some CLR fiddling */
    {
       _value = value;
    }

    public static explicit operator int(MyTest value) /* CLR provides conversions automatically */
    {
       return value._value;
    }
    public static explicit operator MyTest(int value) /* CLR provides conversions automatically */
    {
       return new MyTest(value);
    }

    public static readonly MyTest A = new MyTest(1); /* Should be const, not readonly, but we can't do a const of a custom type in C#. Also, is magically implicitly converted without calling a constructor */

    public static readonly MyTest B = new MyTest(2); /* Ditto */
}

Да, вы можете легко получить "базовое" значение int, но значения A и B по-прежнему строго типизированы как тип MyTest. Это гарантирует, что вы случайно не используете их в тех местах, где они не подходят.

Ответ 2

Итак, здесь я знаю, что мое перечисление - это тип int

Нет, нет. Он имеет базовый тип int, но это отдельный тип. Черт, эта половина точки перечисления в первую очередь - что вы можете сохранить типы раздельными.

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

EDIT: одна странность, о которой вам следует знать, заключается в том, что существует неявное преобразование из постоянного значения 0 в тип перечисления:

Test foo = 0;

Фактически, в реализации MS это может быть любая константа 0:

Test surprise = 0.0;

Это ошибка, но одна из которых слишком поздно исправить:)

Я считаю, что остальное для этого неявного преобразования заключалось в том, чтобы упростить проверку того, установлены ли какие-либо биты в перечислении флагов и другие сравнения, которые будут использовать "значение 0". Лично я не поклонник этого решения, но это стоит, по крайней мере, знать об этом.

Ответ 4

Значения перечисления не относятся к типу int. int является базовым типом перечисления. Перечисления технически интегрированы, но логически (с точки зрения языка С#) нет. int (System.Int32) является базовым типом всех перечислений по умолчанию, если вы явно не указали другой.

Ответ 5

Вы перечисляете тип Test. Это не int только потому, что ваше перечисление имеет значения целых чисел.

Вы можете указать свой enum для получения значения int:

int a = (int) Test.A;