Правило CA1008 указывает, что все перечисления должны иметь значение 0
с именем Unknown
(здесь мы не обсуждаем флаги).Я понимаю причину, по которой вы хотите предотвратить то, чтобы неинициализированные значения автоматически приобретали смысл.Предположим, я определил следующее перечисление:
enum Gender
{
Male,
Female
}
class Person
{
public string Name { get; set; }
public Gender Gender { get; set; }
}
Это указывает на то, что каждый человек должен быть либо мужчиной, либо женщиной (давайте пока не будем обсуждать гендерные вопросы).Если я забуду установить свойство Gender
, то этот человек автоматически станет мужчиной, что может вызвать проблемы.По этой причине я понимаю предупреждение CA1008, поэтому значение 0 должно быть зарезервировано для неизвестного / неинициализированного значения.
Итак, давайте изменим перечисление Gender
на значение 0 и больше не будем использовать:
enum Gender
{
Male = 1,
Female = 2
}
Когда я не указываю пол, тогда это не мужчина или женщина.Проблемы могут возникнуть во время сериализации.Значение 0
не очень наглядно для перечисления во время отладки.Чтобы исправить это и избежать предупреждения CA1008, я снова изменяю перечисление:
enum Gender
{
Unknown = 0,
Male = 1,
Female = 2
}
Неинициализированные свойства теперь отображаются как Unknown
, что выглядит хорошо.Но я, возможно, представил другую проблему, которая заключается в том, что значение Unknown
выглядит как допустимое значение и может быть применено к пользователю.Я также мог бы получить предупреждения о том, что не имею дело со всеми значениями перечисления.Предположим, я использую конструктор, который требует, чтобы я указывал пол и имя, чтобы избежать неинициализированных свойств:
public Person(string name, Gender gender)
{
Name = name ?? throw new ArgumentNullException(name);
Gender = gender;
}
Когда я определяю перечисление Unknown
, тогда я теперь могу явно установить пол в Unknown
,Конечно, это можно проверить в конструкторе, но это будет сигнализироваться только во время выполнения.Если значение Unknown
не определено, то вызывающая сторона может установить его только для мужчины или женщины.
Исправление может заключаться в использовании свойства пола, допускающего значение NULL, поэтому неинициализированное значение является явным null
значение (мы больше не определяем значение Unknown
).Но использование обнуляемых типов делает программирование более сложным, поэтому я бы не советовал.
Применение ObsoleteAttribute
к значению Unknown
может быть хорошей идеей.Когда кто-то явно использует значение, оно помечается как предупреждение (во время сборки).
Как правильно обращаться с неинициализированными значениями перечисления и использует ObsoleteAttribute
- хорошая идея илиесть ли у него другие недостатки?
Примечания: * Хотя устаревшая здесь не является правильной семантикой, это единственный (простой) способ создания предупреждения, если используется значение.* Использование POCO без конструктора по умолчанию может усложнить сериализацию, поэтому вообще плохая идея иметь (сериализуемые) классы без них.