Не уникальные значения перечисления
Я пытаюсь скрыть позиции индекса в файле 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
}
если вы используете это перечисление в бросковом свойстве, вы увидите Зеленый, Зеленый, Синий в дизайнере, а не Красный, Зеленый, Синий.