Использование целочисленного перечисления без приведения в C # - PullRequest
6 голосов
/ 22 ноября 2010

Добрый день, допустим, у меня есть enum

public enum Test : int 
{ 
   TestValue1 = 0, 
   TestValue2, 
   TestValue3 
}

Почему я не могу использовать такие выражения, как Int32 IntTest = Test.TestValue1 без преобразования в значение IntTest = 0?Было бы полезно, если бы я решил позже добавить больше элементов в перечисление?Я думаю, что я вынужден использовать Int32 IntTest = (Int32) Test.TestValue1, который я считаю избыточным ... Кроме того, почему я не могу сделать что-то вроде

switch (IntTest)
{
    case (Test.TestValue1) : DoSomething();
                             break;
    case (Test.TestValue2) : DoSomethingElse();
                             break;
    default                : Do Nothing();
}

?Компилятор говорит, что он ожидает постоянного значения вместо TestValue1 ... Разве это значение не является постоянным?

Большое спасибо.

Ответы [ 9 ]

8 голосов
/ 22 ноября 2010

Вы не можете использовать Int32 и Test взаимозаменяемо, потому что семантически они являются различными типами, даже если они действительно используют один и тот же механизм хранения.

Если вам нужен Int32, тогда используйте Int32; если вам нужен Test, тогда используйте Test; если вам нужно конвертировать между ними, используйте явное приведение.

(И, конечно, язык мог легко быть задан, чтобы неявно разрешать эти преобразования, но такая «особенность», вероятно, создала бы больше проблем, чем решала.)

8 голосов
/ 22 ноября 2010

Обратите внимание, что вы можете сделать это:

switch ((Test)IntTest)
{
    case (Test.TestValue1) : DoSomething();
                             break;
    case (Test.TestValue2) : DoSomethingElse();
                             break;
    default                : DoNothing();
}

Приведение к типу Test из int гарантированно не завершится неудачей, даже если значение не указано в перечислении. Если значение отсутствует в перечислении, вызов ToString () для экземпляра Test вернет строковое представление базового числового значения.

2 голосов
/ 19 ноября 2012
public enum Test
{ 
   TestValue1 = 0, 
   TestValue2, 
   TestValue3 
}

В методе вы можете использовать перечисление в качестве Типа.
Просто включите переменную типа Test, тогда вам не нужно приводить перечисление к int.

public void DoSwitch(Test val)
{
   switch (val)
   {
       case (Test.TestValue1) : DoSomething();
                                break;
       case (Test.TestValue2) : DoSomethingElse();
                                break;
       default                : Do Nothing();
   }
}
2 голосов
/ 13 сентября 2012

Я хотел реализовать перечисление таким же образом, как это, чтобы упростить преобразование приложения, используя имена столбцов таблицы в качестве строк в индексах.

Вот чего я пытаюсь достичь:

enum TableName
{
    Column1Name = 0
}

Column1Data = (cast)objData[RowIndex][TableName.Column1Name];

проблема, как упомянуто выше, состоит в том, что C # требует явного приведения при использовании enum's

Column1Data = (cast)objData[RowIndex][(int)TableName.Column1Name]; //what a waste of time..

Но у меня есть обходной путь .. стоните все, что вы хотите: P (это не производственное приложение - пожалуйста, подумайте о влиянии этого кода перед его реализацией в реальной среде)

public static class TableName
{
    public const int Column1Name = 0;
}

Column1Data = (cast)objData[RowIndex][TableName.Column1Name]; //this is now valid, and my sanity remains intact - as does the integer value ;)
2 голосов
/ 22 ноября 2010

Вы должны разыграть, потому что определение языка говорит, что вы должны разыграть. Резервные? Может быть. Но так оно и есть.

Для вашего switch заявления:

switch (IntTest)
{
    case (int)Test.TestValue1: DoSomething(); break;
}

Значения перечисления должны быть полностью дополнены именем типа перечисления.

1 голос
/ 22 ноября 2010

Как указал Павел, у вас есть синтаксическая ошибка, которая должна разрешить (которую вы, очевидно, исправили) . Как отмечают другие (s), Test - это перечисление, которое содержит значения целого числа. Перечисление может использоваться, например, для простой обработки значений, таких как x0001 или 0xA0BC (41148).

В примере вы использовали Int32 IntTest , который является 32-разрядным целым числом; Я мог бы добавить, что вы должны использовать int вместо Int32 , и если ваше перечисление содержит что-то другое, то целое число даже не указывает : int , поскольку тип удержания по умолчанию действительно целочисленный.

Относительно причины, по которой компилятор заставляет вас указывать значение; Как это работает, перечисление НЕ является целым числом, только значения его возможных под-свойств (TestValue1, TestValue2, TestValue3) являются целыми числами. *

Как кто-то указал, что будет напечатано в консоли. WriteLine не является целым числом. *

1 голос
/ 22 ноября 2010

Эй, эй, я только что прочитал эту главу в своей книге.

Первое, что я хотел бы упомянуть, вы пытаетесь это

Console.WriteLine(Test.TestValue1);

Вы заметите что-то.

Вывод не является числом или даже целым числом.

Кроме того, это должно ответить и на ваш второй вопрос.

Так что вы должны явно приводить ваше перечисление к целому числу каждый раз.

:)

1 голос
/ 22 ноября 2010

перечисления работают так, как задуманоКак говорит msdn:

Базовый тип указывает, сколько памяти выделяется для каждого перечислителя.Однако явное приведение необходимо для преобразования типа enum в целочисленный тип.

0 голосов
/ 22 ноября 2010
  • Во-первых, часть : int вашего перечисления полностью избыточна, поскольку int уже является типом управления по умолчанию для перечисления.

  • Требуется приведение, потому что когда вы пишете enum, вы на самом деле определяете новый Type, очень похоже на класс. Любое значение перечисления с именем Test имеет тип Test.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...