Неуникальные значения перечисления - PullRequest
46 голосов
/ 08 ноября 2011

Я пытаюсь скрыть позиции индекса в файле edi ... У меня была ситуация, когда 2 или 3 вещи могли быть с индексом в зависимости от ситуации. Было бы здорово использовать enum, чтобы скрыть «магические числа», и был удивлен, увидев, что вы можете назначить несколько перечислений одному и тому же значению, например так:

public enum Color
{
    Red = 1,
    Blue = 1,
    Green = 1
}

и компилятор этим доволен. Я не ожидал, что это сработает. Мне не нужно возвращаться к перечислению, поэтому я не беспокоюсь о попытке вернуться, но это пахнет в стиле фанк. Почему CLR допускает множественные значения для перечислений, и я должен использовать структуру для этого? (Структура казалась более тяжелой, чем перечисление, и это, кажется, работает)

Ответы [ 6 ]

72 голосов
/ 08 ноября 2011

На самом деле вы уже определяете структуру ... За кулисами перечисление - это просто структура (но которая происходит от System.Enum), а значения перечисления определяются как константы (вы можете проверить это с помощью ILDASM) .

Ваше определение enum преобразуется в следующий псевдо-код C #:

public struct Color : System.Enum
{
    public const int Red = 1;
    public const int Blue = 1;
    public const int Green = 1;
}

Приведенный выше код не будет компилироваться в C #, потому что компилятор не позволяет определять структуру с явным базовым классом, но это то, что он выдает для определения перечисления.

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

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

Color color1 = (Color)1;
Color color2 = (Color)Enum.Parse(typeof(Color), "1");

Строго говоря, значение перечисления не Red, а 1, но когда вы распечатаете значение, вы увидите Red.

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

// true (Red is Green??)
bool b = Color.Red == Color.Green;

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

Вот прямая ссылка на раздел моего учебника .NET, в котором обсуждаются перечисления под капотом: http://motti.me/c1E

18 голосов
/ 08 ноября 2011

Это совершенно законно C #.Из спецификации C # Language версии 4.0, раздел 14.3:

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

enum Color 
{
   Red,
   Green,
   Blue,
   Max = Blue
}

показано перечисление, в котором два члена перечисления - синий и максимальный - имеют одинаковое связанное значение.

11 голосов
/ 08 ноября 2011

То же числовое значение, но другое имя - ничто иное, как псевдоним. Это может быть, например,

public enum Color
{
   DefaultColor = 1,
   Red = 1,
   Blue = 2
}

Это может иметь смысл в некоторых случаях, но не во многих. Когда вы анализируете значения обратно и вызываете colorValue.ToString (), вы получите последнее значение как строковое значение обратно (в данном случае Red), но вы потеряете концепцию цветов по умолчанию, поскольку это одно и то же. По крайней мере, так, как вы смоделировали свои данные. Если вы хотите сохранить это отдельно, используйте разные значения для разных вещей.

5 голосов
/ 16 декабря 2015

Это было бы вполне приемлемое определение:

public enum AllTheThings
{
    TheMoney = 1,
    TheFreeRides = 1,
    TheLieThatYouDenied = 2,
    TheCallsYouveBeenMaking = 3,
    TheTimesYouveBeenFaking = 4
}
3 голосов
/ 08 ноября 2011

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

public enum MyColor 
{ 
    Blue = 2,         
    Yellow = 3,
    Green = 4
    BlueAndYellow = 4,        
} 

Так же, как:

public enum MyColor 
{ 
    Blue = 2,         
    Yellow = 3,
    Green = 4,
    BlueAndYellow = Green,        
} 

По сути, у вас просто одна и та же константа с двумя разными именами. BlueAndYellow это псевдоним для Green.

1 голос
/ 07 октября 2014

Здесь следует отметить, что неуникальные значения приводят к отсутствию и дублированию значений в конструкторе Visual Studio.

public enum MyColor
{
Red= 1,
Green= 1,
Blue= 2
}

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

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