В чем разница между перечислениями и использованием статических классов с константами?

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

public enum SomeEnum
{
   One = 1,
   Two,
   Three
}

public static class SomeClass
{
   public static readonly int One = 1;
   public static readonly int Two = 2;
   public static readonly int Three = 3;
}

person IAmAN00B    schedule 05.04.2011    source источник
comment
Помимо безопасности типов (уже ответили), вы можете использовать атрибут Flags в перечислении, который может быть полезен в некоторых приложениях.   -  person Josh Anderson    schedule 06.04.2011


Ответы (3)


Разница заключается в безопасности типов. Предположим, у вас есть два таких перечисления. Как вы собираетесь сказать разницу:

void SomeMethod(int x, int y)

// Compiles, but won't do what you want.
SomeMethod(SomeOtherClass.Xyz, SomeClass.One);

vs

void SomeMethod(SomeEnum x, SomeOtherEnum y)

// Compile-time error
SomeMethod(SomeOtherEnum.Xyz, SomeEnum.One)

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

person Jon Skeet    schedule 05.04.2011

Перечисления встроены непосредственно в IL, тогда как для полей (таких, как те, которые есть в вашем классе) потребуется инструкция загрузки поля, которая может быть немного дороже. Вот код IL для вызова метода, который принимает перечисление вместо полей.

 IL_0001:  ldc.i4.1
  IL_0002:  call       void ConsoleApplication2.Program::TestMethod(valuetype ConsoleApplication2.SomeEnum)
  IL_0007:  nop
  IL_0008:  ldc.i4.3
  IL_0009:  call       void ConsoleApplication2.Program::TestMethod(valuetype ConsoleApplication2.SomeEnum)
  IL_000e:  nop
  IL_000f:  ldsfld     int32 ConsoleApplication2.SomeClass::Two
  IL_0014:  call       void ConsoleApplication2.Program::TestMethod(int32)
  IL_0019:  nop
  IL_001a:  ldsfld     int32 ConsoleApplication2.SomeClass::One
  IL_001f:  call       void ConsoleApplication2.Program::TestMethod(int32)
person sarvesh    schedule 05.04.2011
comment
IL пугает некоторых. Выход отражателя столь же убедителен. Я согласен с общим аргументом времени компиляции и времени загрузки. - person GregC; 06.04.2011

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

void Foo(значение SomeEnum);

В то время как с вашим статическим классом мне пришлось бы использовать параметр int. Конечно, вы можете отказаться от безопасности типов, но она проще в использовании и делает ее более очевидной, и вы также можете легче выполнять преобразования. Кроме того, перечисления дают автоматически увеличивающиеся значения, поддержку красивой печати в отладчике, преимущества связывания с элементами управления, такими как сетка свойств. Вы поняли идею.

person Ed S.    schedule 05.04.2011