Исправить исключение NullReferenceException можно с помощью Null-условных операторов в c # 6 и написать меньше кода для обработки нулевых проверок.
Он используется для проверки нуля до выполнения доступа к члену (?. ) или index (? [).
Пример
var name = p?.Spouse?.FirstName;
эквивалентен:
if (p != null)
{
if (p.Spouse != null)
{
name = p.Spouse.FirstName;
}
}
В результате имя будет нулевым когда p равно null или когда p.Spouse имеет значение null.
В противном случае имени переменной будет присвоено значение p.Spouse.FirstName.
Для получения дополнительной информации: Операторы с нулевым условием
Эксперимент показывает, что:
V1 = "value1"
blockquote>и
V2 = "value1"
blockquote>Однако это не гарантируется. На странице MSDN на
Enum.GetName
указано:Если несколько элементов перечисления имеют одно и то же базовое значение, метод GetName гарантирует, что он вернет имя одного из этих перечисляющих членов. Однако он не гарантирует, что он всегда будет возвращать имя того же элемента перечисления. В результате, когда несколько элементов перечисления имеют одинаковое значение, ваш код приложения никогда не должен зависеть от метода, возвращающего имя определенного члена.
blockquote>
Из раздела «Замечания» в документации по Enum.GetName
методу ( http://msdn.microsoft.com/en-us/library/system.enum.getname.aspx ), это говорит:
Если несколько элементов перечисления имеют одно и то же базовое значение, метод GetName гарантирует, что он вернет имя одного из этих элементов перечисления. Однако он не гарантирует, что он всегда будет возвращать имя того же элемента перечисления. В результате, когда несколько элементов перечисления имеют одно и то же значение, ваш код приложения никогда не должен зависеть от метода, возвращающего имя конкретного члена.
blockquote>Я проверил тест, чтобы увидеть, что произойдет на опыте, и он всегда возвращал первое значение, определенное (в вашем примере, значение1), но согласно официальной документации выше, вы не можете полагаться на это (см. комментарий @ gluk47, указывающий на другое поведение в дикой природе) .
Хорошо, потому что нет никаких гарантий относительно порядка, и устаревший атрибут, похоже, не влияет на методы Enum
, я обычно предлагаю использовать свойство string для целей сериализации и использовать собственный код для обработки устаревших значений.
Таким образом, первичный Enum
не имеет дубликатов и содержит только текущие значения.
В зависимости от структуры сериализации вы можете пометить свойство строки как сериализуемое, но устаревшее, а фактическое свойство, используемое в коде, которое игнорируется путем сериализации.
Чтобы обрабатывать устаревшие значения в наборе свойств строки, вы можете либо использовать [Obsolete] enum
, либо оператор switch. Как правило, я бы, вероятно, использовал бывшую, если у меня много устаревших значений для обработки, а последнее, если у меня есть только несколько значений для обработки.
Также может иметь смысл поставить код в помощнике класс или метод расширения, особенно если вы загружаете или сохраняете это значение из нескольких мест.
Хотя я не очень много пробовал в производственном коде, мне интересно, было бы лучше использовать struct
вместо enum
, чтобы иметь больше контроля ... но я думаю, что ему нужно много шаблонов, которые не могут быть легко сделаны родовыми.
Я не согласен с другими утверждениями ответов
... это не гарантируется ...
... вы не можете полагаться на этом ...
blockquote>, а также с утверждением msdn:
... ваш код приложения никогда не должен зависеть от метода, возвращающего имя определенного члена ...
blockquote>История
В моем программном обеспечении
enum Blabla { A = 0, B = 1, C = 2, D = 3 }
было перечислено значение
AAA
, значение которого изменяется наAA
, а затемAA
изменяется наAAA
. Чтобы сохранить обратную совместимость, мне пришлось делатьenum Blabla { A = 0, AA = 0, AAA = 0, B = 1, C = 2, D = 3 }
. Это позволяет десериализовать значение старого enum (сделанное более старыми версиями программного обеспечения) как
AAA
.Затем был отчет который печатает значение
Blabla
. И в какой-то момент каждый клиент, использующий новую версию, начинает рассказывать мне, что вместоAAA
они видят значениеAA
. Все они видятAA
(и никто из них не видитA
).Что я сделал? Я просто изменяю порядок (пока результат не был
AAA
)enum Blabla { AAA = 0, A = 0, AA = 0, ...}
и сделал тест, чтобы убедиться, что
Blabla.AAA
будет выводиться какAAA
. Проблема решена?Доказательство
Глядя на источники
Enum.ToString()
(илиEnum.GetName()
), он использует GetEnumName () , который вызываетArray.BinarySearch()
для отсортированного массива значений, чтобы найти индекс значения.Результатом двоичного поиска является детерминированный : при условии, что он с теми же параметрами вернет тот же результат.
Итак:
- , если вы не изменяете enum, тогда результат будет таким же.
- можно найти результат экспериментально (или, возможно, понимая, как бинарный поиск работает и как будет обрабатываться enum).
- нет простого правила для определения результата (например, вы не можете сказать, что он всегда возвращает первое определенное значение »).
- маловероятно, что формат
enum
будет изменен (например, порядок определения и порядок перечня значений отличается) илиEnum.ToString()
будет изменен, однако это может произойти, поэтому убедитесь, что у вас есть тесты для случаи, когда вы полагаетесь на возвращаемое значение.