Enum печатает неожиданную строку, когда указывает на другую [дубликат]

Исправить исключение 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.

Для получения дополнительной информации: Операторы с нулевым условием

10
задан John Saunders 18 March 2012 в 01:24
поделиться

4 ответа

Эксперимент показывает, что:

V1 = "value1"

и

V2 = "value1"

Однако это не гарантируется. На странице MSDN на Enum.GetName указано:

Если несколько элементов перечисления имеют одно и то же базовое значение, метод GetName гарантирует, что он вернет имя одного из этих перечисляющих членов. Однако он не гарантирует, что он всегда будет возвращать имя того же элемента перечисления. В результате, когда несколько элементов перечисления имеют одинаковое значение, ваш код приложения никогда не должен зависеть от метода, возвращающего имя определенного члена.

14
ответ дан ChrisF 23 August 2018 в 19:02
поделиться

Из раздела «Замечания» в документации по Enum.GetName методу ( http://msdn.microsoft.com/en-us/library/system.enum.getname.aspx ), это говорит:

Если несколько элементов перечисления имеют одно и то же базовое значение, метод GetName гарантирует, что он вернет имя одного из этих элементов перечисления. Однако он не гарантирует, что он всегда будет возвращать имя того же элемента перечисления. В результате, когда несколько элементов перечисления имеют одно и то же значение, ваш код приложения никогда не должен зависеть от метода, возвращающего имя конкретного члена.

Я проверил тест, чтобы увидеть, что произойдет на опыте, и он всегда возвращал первое значение, определенное (в вашем примере, значение1), но согласно официальной документации выше, вы не можете полагаться на это (см. комментарий @ gluk47, указывающий на другое поведение в дикой природе) .

2
ответ дан Ethan Brown 23 August 2018 в 19:02
поделиться

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

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

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

Чтобы обрабатывать устаревшие значения в наборе свойств строки, вы можете либо использовать [Obsolete] enum, либо оператор switch. Как правило, я бы, вероятно, использовал бывшую, если у меня много устаревших значений для обработки, а последнее, если у меня есть только несколько значений для обработки.

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

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

0
ответ дан Phil1970 23 August 2018 в 19:02
поделиться

Я не согласен с другими утверждениями ответов

... это не гарантируется ...

... вы не можете полагаться на этом ...

, а также с утверждением msdn:

... ваш код приложения никогда не должен зависеть от метода, возвращающего имя определенного члена ...

История

В моем программном обеспечении

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() будет изменен, однако это может произойти, поэтому убедитесь, что у вас есть тесты для случаи, когда вы полагаетесь на возвращаемое значение.
2
ответ дан Sinatr 23 August 2018 в 19:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: