Не уникальные значения перечисления

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

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

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

Ответ 1

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

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

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

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

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

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

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

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

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

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

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

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

Ответ 2

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

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

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

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

Ответ 3

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

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

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

Ответ 4

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

public enum AllTheThings
{
    TheMoney = 1,
    TheFreeRides = 1,
    TheLieThatYouDenied = 2,
    TheCallsYouveBeenMaking = 3,
    TheTimesYouveBeenFaking = 4
}

Ответ 5

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

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

То же, что и:

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

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

Ответ 6

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

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

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