Как определить, установлено ли свойство enum? С# - программирование
Подтвердить что ты не робот

Как определить, установлено ли свойство enum? С#

У меня есть класс с свойством enum:

public class Foo
{
    public Color ColorType {get;set;}
}

public enum Color
{
    Red,
    Green,
}

Теперь этот класс можно инициализировать следующим образом:

var foo = new Foo();

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

private void checkEnum(Foo foo)
{
    if(foo.ColorType !=null)
    {
        //perform these actions
    }else
    {
        //perform those actions
    }
}

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

4b9b3361

Ответ 1

Вы можете использовать один из двух методов: значение enum по умолчанию или нулевое перечисление.

Значение перечисления по умолчанию

Поскольку перечисление поддерживается целым числом, а int по умолчанию равно нулю, перечисление всегда будет инициализировать по умолчанию значение, равное нулю. Если вы явно не назначаете значения enum, первое значение всегда будет равным нулю, второе - одному и т.д.

public enum Color
{
  Undefined,
  Red,
  Green
}

// ...

Assert.IsTrue(Color.Undefined == 0);  // success!

Nullable enum

Другим способом обработки неназначенного перечисления является использование поля с нулевым значением.

public class Foo
{
   public Color? Color { get; set; }
}

// ...

var foo = new Foo();
Assert.IsNull(foo.Color);     // success!

Ответ 2

Вы можете сделать это так, чтобы лежащее в основе частное поле было нулевым, но свойство не является.

например.

class SomeClass
{
    private Color? _color; // defaults to null

    public Color Color
    {
        get { retrun _color ?? Color.Black; }
        set { _color = value; }
    }

    public bool ColorChanged
    {
        get { return _color != null; }
    }
}

Таким образом, если color == null, вы знаете, что он еще не установлен, и вы также запрещаете пользователю устанавливать его в null (или undefined, как указывают другие ответы). Если color - null, у вас есть 100% уверенность в том, что пользователь еще не установил его.

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

Вы также можете сделать это еще на один шаг, сделав так, чтобы set устанавливал только поле, если заданное значение не равно значению по умолчанию (в зависимости от вашего варианта использования):

public Color Color
{
    get { retrun _color ?? Color.Black; }
    set
    {
        if (value != Color)
        {
            _color = value;
        }
    }
}

Ответ 3

У вас есть два реальных варианта. Первый заключается в добавлении значения undefined в перечисление. Это будет значение по умолчанию перед инициализацией свойства.

1)

public enum Color
{
    Undefined,
    Red,
    Green,
}

С вашей проверкой:

private void checkEnum(Foo foo)
{
    if(foo.ColorType == Color.Undefined)
    {
        //perform these actions
    }else
    {
        //perform those actions
    }
}

2) В качестве альтернативы вы не можете добавить значение undefined и просто создать свойство Nullable

public class Foo
{
    public Color? ColorType {get;set;}
}
public enum Color
{
    Red,
    Green,
}

И выполните свой чек, например:

private void checkEnum(Foo foo)
{
    if(!foo.ColorType.HasValue)
    {
        //perform these actions
    }else
    {
        //perform those actions
    }
}

Ответ 4

Перечисления Типы значений, что означает, что они не являются ссылками на объект, хранящийся где-то еще, и, следовательно, они не могут быть null. Они всегда имеют значение по умолчанию, точно так же, как int, которое по умолчанию будет равно нулю при создании. Я предлагаю два подхода:

  • Добавьте еще одну запись enum, называемую, например, None со значением, равным нулю. Таким образом, ваше значение enum по умолчанию будет None при создании. Затем вы можете проверить if(foo.ColorType != Color.None).

  • Сделайте свой объект Color нулевым, например: public Color? ColorType { get; set; }. Теперь по умолчанию будет null и ему может быть присвоено значение null. Подробнее о nullable типах здесь: MSDN - Nullable Types (С#).

Ответ 5

enum - тип значения, поэтому он не может быть нулевым, а хранилище обычно является целым числом. Если вы хотите использовать undefined для своего типа, вы можете иметь

public enum Color
{
    Undefined,
    Red,
    Green,
}

Ответ 6

Как вы обнаружили, перечисления в С# представляют собой типы значений (они по существу целые), а не ссылочные типы, поэтому они не будут по умолчанию иметь значение NULL, а самое меньшее целочисленное значение в перечислении. Не упускайте из виду эти отношения при работе с перечислениями, поскольку это один из их самых полезных атрибутов. Всегда помните, что прямо укажите это или нет,

public enum Color
{
    Red,
    Green
}

соответствует:

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

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

Что касается того, есть или нет лучший способ сделать это, все зависит от того, что "this", хотя нет ничего плохого в вашем предположении просто использовать следующую настройку enum:

public enum Color
{
    None = 0,
    Red,
    Green
}

Как правило, вы хотите использовать перечисления, когда у вас есть определенно конечный и дискретный набор возможных значений, которые вы хотите выбрать по имени. Например, предположим, что у меня есть метод, который берет одно из четырех основных направлений (Север, Восток, Юг, Запад) в качестве параметра. Я решаю, что хочу пронумеровать каждое из направлений по часовой стрелке, начиная с 0 для Севера.

public enum Direction
{
    North = 0,
    East,
    South,
    West
}

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

getNeighbor(1);

читается намного проще:

getNeighbor(Direction.East);