Я не знаю о причинах этого проектного решения, но мы можем взглянуть на некоторые из его последствий.
Давайте посмотрим на IL-представление перечисления:
.class private auto ansi sealed MyEnum
extends [mscorlib]System.Enum
{
// Fields
.field public specialname rtspecialname int32 value__
.field public static literal valuetype MyEnum Value0 = int32(0)
.field public static literal valuetype MyEnum Value1 = int32(1)
.field public static literal valuetype MyEnum Value2 = int32(2)
}
Сначала отметим, что это тип значения и, следовательно, (MyEnum)0
должно быть допустимым. Во-вторых, мы видим, что возможные значения перечислений равны всего const
с, а перечисления на уровне времени выполнения совместимы по присваиванию с целочисленными литералами.
Константы перечисления обычно становятся целочисленными литералами. Поэтому, если вы хотите предотвратить появление недопустимых перечислений, вам потребуется ввести дорогостоящие проверки времени выполнения при преобразовании из перечисления или нетривиальные проверки времени загрузки кросс-сборки, чтобы убедиться, что литералы перечисления, выпекаемые в другой сборке, действительны.
Другое дело, что можно создавать перечисления, поддерживаемые long. Но одно свойство longs заключается в том, что их назначение не гарантируется как атомарное. Поэтому гарантировать, что значение перечисления на основе long
действительно, трудно.
enum MyLongEnum:long
{
Value1=0x0101010102020202,
Value2=0x0303030304040404
}
Если вы присвоили такое перечисление из нескольких потоков, вы можете получить смешанное значение, которое недопустимо, даже если вы никогда не назначали недопустимое значение.
Существует также простой обходной путь для получения безопасных перечислений: используйте класс с закрытым конструктором и статическими полями или свойствами только для чтения для возможных значений. Таким образом вы потеряете целочисленные преобразования, литералы и ненулевые значения, но получите безопасность типов и улучшенное управление версиями.