Информация об изменениях

Сообщение Re: Подводные камни enum от 08.05.2019 5:10

Изменено 08.05.2019 6:41 Sinclair

Re: Подводные камни enum
Здравствуйте, varenikAA, Вы писали:

AA>В процессе работы заметил, что

AA>enum довольно "слабый" тип, который скорее является простым алиасом/набором констант для
AA>численных типов.
AA>Так, доступим есть тип
AA>
 
AA>enum Month
AA>{
AA>    Jan = 1,
AA>    Feb = 2
AA>}
AA>

AA>тогда, если
AA>
AA>var zero = default(Month); //=> 0
AA>

AA>или
AA>
AA>var m = (Month)10; //=> 10!!!
AA>var t = m.GetType(); //=> Month!!!
AA>


AA>Т.е. что первый код, что второй приводят к скрытой ошибке.

Пока непонятно, в чём именно ошибка.
AA>Таким образом, мы вынужденны всегда проверять значение через
AA>
Enum.IsDefined

AA>, что согласитесь неудобно.
Примерно также реализованы енумы в С/С++. На выбор реализации енумов в дотнет существенно повлияли соображения интероперабельности с неуправляемым кодом.
К примеру, Flags-енумы вполне легально включают значения, не сводимые ни к одному из членов перечисления.
Теоретически, можно было бы разделить енумы на два подкласса — flags и unique; но это скорее затруднит, чем облегчит, их использование. И весьма существенно увеличит стоимость реализации.
Например, CLR устроен так, что все value-типы инициализируются битовыми нулями. Но вы совершенно не обязаны включать значение 0 в перечисление:
public enum Fail {Correct = 1}; 
...
var fail = new Fail[1]; //Омг, что у меня в Fail[0]?


Если лично вам очень нужен енум с более жёстким поведением, вы всегда можете его свелосипедить:
public struct StrictEnum<E> where E: struct, Enum
{
  private E _value;
  public StrictEnum(E value) => _value  ? 
  {
    if(!= Enum.IsDefined(typeof(E), value))
    throw new ArgumentException();
    _value = value;
  }
  ...
}
Re: Подводные камни enum
Здравствуйте, varenikAA, Вы писали:

AA>В процессе работы заметил, что

AA>enum довольно "слабый" тип, который скорее является простым алиасом/набором констант для
AA>численных типов.
AA>Так, доступим есть тип
AA>
 
AA>enum Month
AA>{
AA>    Jan = 1,
AA>    Feb = 2
AA>}
AA>

AA>тогда, если
AA>
AA>var zero = default(Month); //=> 0
AA>

AA>или
AA>
AA>var m = (Month)10; //=> 10!!!
AA>var t = m.GetType(); //=> Month!!!
AA>


AA>Т.е. что первый код, что второй приводят к скрытой ошибке.

Пока непонятно, в чём именно ошибка.
AA>Таким образом, мы вынужденны всегда проверять значение через
AA>
Enum.IsDefined

AA>, что согласитесь неудобно.
Примерно также реализованы енумы в С/С++. На выбор реализации енумов в дотнет существенно повлияли соображения интероперабельности с неуправляемым кодом.
К примеру, Flags-енумы вполне легально включают значения, не сводимые ни к одному из членов перечисления.
Теоретически, можно было бы разделить енумы на два подкласса — flags и unique; но это скорее затруднит, чем облегчит, их использование. И весьма существенно увеличит стоимость реализации.
Например, CLR устроен так, что все value-типы инициализируются битовыми нулями. Но вы совершенно не обязаны включать значение 0 в перечисление:
public enum Fail {Correct = 1}; 
...
var fail = new Fail[1]; //Омг, что у меня в Fail[0]?


Если лично вам очень нужен енум с более жёстким поведением, вы всегда можете его свелосипедить:
public struct StrictEnum<E> where E: struct, Enum
{
  private E _value;
  public StrictEnum(E value) 
  {
    if(!= Enum.IsDefined(typeof(E), value))
    throw new ArgumentException();
    _value = value;
  }
  ...
}