Я искал и не смог найти дубликат. Если вы можете предоставить ссылку, я удалю этот вопрос.
Эрик Вейльну
1
иногда использование оператора switch не является наилучшей практикой (когда у вас большие перечисления), вместо этого вы можете использовать Dict <>
Guy L
1
Если вы хотите повысить производительность, вы можете использовать класс, описанный в этой статье codeproject.com/KB/dotnet/enum.aspx . Использование будет выглядеть следующим образом: Enum <YourEnum> .ToString (yourValue) или Enum <YourEnum> .ToString ((int) yourValue)
ideafixxxer
5
Кодирование, чтобы не сломать точечную дефекацию, является воплощением хвоста, виляющего собакой. Производители ПО не думают: «Давайте сделаем отличное приложение, чтобы у dotfuscator было чем заняться». Dofuscator существует, чтобы помочь облегчить развитие SW. Если это не может сделать это ... может это!
micahhoover
Ответы:
127
Начиная с C # 6, лучший способ получить имя перечисления - это новый nameofоператор:
nameof(MyEnum.EnumValue);// Ouputs>"EnumValue"
Это работает во время компиляции, при этом перечисление заменяется строкой в скомпилированном результате, что, в свою очередь, означает, что это самый быстрый возможный способ.
Любое использование имен enum мешает запутыванию кода, если вы считаете, что запутывание имен enum стоит или важно - это, вероятно, совсем другой вопрос.
Это заслуживает большего внимания. Несмотря на очевидное ограничение, то есть требование ввода во время компиляции. На мой взгляд, это должно быть предпочтительным, когда это возможно . «Переименовать» и «найти все ссылки» также учитывают это, потенциально избегая магических строк и дублирующих констант.
Тимо
1
Так что я думаю, что это не сработает, если значение enum определено во время выполнения? Пример: MyEnum variableEnum; variableEnum = setEnumValueMethod (); nameof (variableEnum);
Maxter
1
@ Макстер нет, как nameof(variableEnum)будет "variableEnum". Он отражает (во время сборки) имя поля / свойства / параметра / переменной, а не значение .
Кит
вы. к сожалению, не работает, если вы делаете это: var someEnumvalue = SomeEnum.FooBar; nameof (someEnumvalue);
Жалко
1
@ Конечно, да, это вернется "someEnumValue", а вам нужно nameof(SomeEnum.FooBar)получить "FooBar".
Enum.GetName принимает значение в качестве аргумента объекта. Это означает, что значение будет упаковано, и это будет тратить ресурсы ЦП на распределение и сборку мусора. Если это выполняется много времени, Enum.GetName будет иметь гораздо меньшую пропускную способность, чем кэширование значений в словаре и поиск имени в нем.
Бежал
@Ran, так что такое решение, которое вместо этого использовать?
Shaijut
Это должен быть ответ
Squbly
делает мой проект медленнее. toString () быстрее.
d2k2
29
В моих тестах Enum.GetNameбыл быстрее и с приличным запасом. Внутренние ToStringзвонкиEnum.GetName . Из источника для .NET 4.0, основы:
publicoverrideStringToString(){returnEnum.InternalFormat((RuntimeType)GetType(),GetValue());}privatestaticStringInternalFormat(RuntimeType eT,Objectvalue){if(!eT.IsDefined(typeof(System.FlagsAttribute),false)){String retval =GetName(eT,value);//<== the oneif(retval ==null)returnvalue.ToString();elsereturn retval;}else{returnInternalFlagsFormat(eT,value);}}
Не могу сказать, что в этом причина, но тесты показывают, что один быстрее другого. Оба вызова включают в себя бокс (на самом деле это вызовы отражения, вы, по сути, извлекаете имена полей) и могут быть медленными по вашему вкусу.
Испытательная установка : перечисление с 8 значениями, нет. итераций = 1000000
Результат : Enum.GetName => 700 мс, ToString => 2000 мс
Если скорость не заметна, я бы не заботился и не использовал ToString так как она предлагает более чистый вызов. Контраст
Все это внутренне вызывает вызов метода InternalGetValueAsString. Разница между ToStringи GetNameбудет в том, что GetNameсначала нужно проверить несколько вещей:
Введенный вами тип не является нулевым.
Тип, который вы ввели, фактически является перечислением.
Значение, которое вы передали, не равно нулю.
Переданное вами значение имеет тип, который перечисление может фактически использовать в качестве своего базового типа, или тип самого перечисления. Он использует GetTypeзначение, чтобы проверить это.
.ToStringне нужно беспокоиться ни об одной из перечисленных выше проблем, поскольку он вызывается для экземпляра самого класса, а не для переданной версии, поэтому из-за того, что .ToStringметод не имеет таких же проблем проверки в качестве статических методов я бы заключил, что.ToString это самый быстрый способ получить значение в виде строки.
где вы это проверили? Какая была сборочная версия? Я получаю очень разные результаты.
nawfal
17
Лучшее, что я могу найти, - это не связанный вопрос на MSDN , который содержит фрагмент XML, который отвечает на этот вопрос. Любой из этих методов имеет один и тот же недостаток: они вызывают enum.toString(), что не работает должным образом при использовании Dotfuscation . Другие проблемы, по-видимому, связаны с косвенным боксом (GetName и Format). К сожалению, я не могу найти никаких причин производительности для использования любого из вышеперечисленного.
Передача перечисленного в штучной упаковке перечисления в string.Format () или любую другую функцию может привести к вызову enum.ToString(). Это вызовет проблемы при расфокусировке. Вы не должны использовать enum.ToString(), enum.GetNames(), enum.GetName(), enum.Format()или enum.Parse()преобразовать перечисление в строку. Вместо этого используйте оператор switch, а также при необходимости интернационализируйте имена.
Format()на самом деле просто обертка GetName()с некоторыми функциями форматирования (или, InternalGetValueAsString()если быть точным). ToString()в значительной степени так же , как Format(). Я думаю, что GetName()это лучший вариант, поскольку совершенно очевидно, что он делает для тех, кто читает источник.
Я создаю метод расширения «Description» и присоединяю его к перечислению, чтобы получить действительно удобное для пользователя наименование, включающее пробелы и регистр. Мне никогда не нравилось использовать само значение enum в качестве отображаемого текста, потому что это то, что мы разработчики используем для создания более читабельного кода. Он не предназначен для отображения пользовательского интерфейса. Я хочу иметь возможность изменять пользовательский интерфейс, не проходя и не меняя перечисления во всем.
Я не знаю, что такое «предпочтительный» метод (спросите 100 человек и получите 100 разных мнений), но делаю то, что проще и работает. GetNameработает, но требует гораздо больше нажатий клавиш. ToString()кажется, делает работу очень хорошо.
ToString()дает наиболее очевидный результат с точки зрения читабельности при использованииEnum.GetName() требует немного больше умственного анализа, чтобы быстро понять, что он пытается сделать (если вы не видите шаблон все время).
С точки зрения производительности, как уже было указано в ответе @ nawfal, Enum.GetName()лучше.
Если производительность действительно является вашей целью, то было бы еще лучше заранее выполнить поиск (используя словарь или другое сопоставление).
В C ++ / CLI это будет выглядеть так
Dictionary<String^,MyEnum> mapping;for each (MyEnum field in Enum::GetValues(MyEnum::typeid)){
mapping.Add(Enum::GetName(MyEnum::typeid), field);}
Сравнение с использованием перечисления 100 элементов и 1000000 итераций:
Ответы:
Начиная с C # 6, лучший способ получить имя перечисления - это новый
nameof
оператор:Это работает во время компиляции, при этом перечисление заменяется строкой в скомпилированном результате, что, в свою очередь, означает, что это самый быстрый возможный способ.
Любое использование имен enum мешает запутыванию кода, если вы считаете, что запутывание имен enum стоит или важно - это, вероятно, совсем другой вопрос.
источник
nameof(variableEnum)
будет"variableEnum"
. Он отражает (во время сборки) имя поля / свойства / параметра / переменной, а не значение ."someEnumValue"
, а вам нужноnameof(SomeEnum.FooBar)
получить"FooBar"
.Работает для нашего проекта ...
источник
В моих тестах
Enum.GetName
был быстрее и с приличным запасом. ВнутренниеToString
звонкиEnum.GetName
. Из источника для .NET 4.0, основы:Не могу сказать, что в этом причина, но тесты показывают, что один быстрее другого. Оба вызова включают в себя бокс (на самом деле это вызовы отражения, вы, по сути, извлекаете имена полей) и могут быть медленными по вашему вкусу.
Если скорость не заметна, я бы не заботился и не использовал
ToString
так как она предлагает более чистый вызов. Контрастс участием
источник
Enum.GetName (...)
Это самый элегантный метод, который предназначен для этого.
Хотя я не вижу никаких проблем с вызовом, так
.ToString()
как он просто короче.С новым синтаксисом C # 6 вы можете использовать:
источник
Все это внутренне вызывает вызов метода
InternalGetValueAsString
. Разница междуToString
иGetName
будет в том, чтоGetName
сначала нужно проверить несколько вещей:GetType
значение, чтобы проверить это..ToString
не нужно беспокоиться ни об одной из перечисленных выше проблем, поскольку он вызывается для экземпляра самого класса, а не для переданной версии, поэтому из-за того, что.ToString
метод не имеет таких же проблем проверки в качестве статических методов я бы заключил, что.ToString
это самый быстрый способ получить значение в виде строки.источник
Лучшее, что я могу найти, - это не связанный вопрос на MSDN , который содержит фрагмент XML, который отвечает на этот вопрос. Любой из этих методов имеет один и тот же недостаток: они вызывают
enum.toString()
, что не работает должным образом при использовании Dotfuscation . Другие проблемы, по-видимому, связаны с косвенным боксом (GetName и Format). К сожалению, я не могу найти никаких причин производительности для использования любого из вышеперечисленного.Перефразируя из фрагмента XML ,
источник
Enum.GetName()
Format()
на самом деле просто оберткаGetName()
с некоторыми функциями форматирования (или,InternalGetValueAsString()
если быть точным).ToString()
в значительной степени так же , какFormat()
. Я думаю, чтоGetName()
это лучший вариант, поскольку совершенно очевидно, что он делает для тех, кто читает источник.источник
Я создаю метод расширения «Description» и присоединяю его к перечислению, чтобы получить действительно удобное для пользователя наименование, включающее пробелы и регистр. Мне никогда не нравилось использовать само значение enum в качестве отображаемого текста, потому что это то, что мы разработчики используем для создания более читабельного кода. Он не предназначен для отображения пользовательского интерфейса. Я хочу иметь возможность изменять пользовательский интерфейс, не проходя и не меняя перечисления во всем.
источник
Я не знаю, что такое «предпочтительный» метод (спросите 100 человек и получите 100 разных мнений), но делаю то, что проще и работает.
GetName
работает, но требует гораздо больше нажатий клавиш.ToString()
кажется, делает работу очень хорошо.источник
Для поклонников VB:
источник
Это тоже сработало бы.
источник
ToString()
дает наиболее очевидный результат с точки зрения читабельности при использованииEnum.GetName()
требует немного больше умственного анализа, чтобы быстро понять, что он пытается сделать (если вы не видите шаблон все время).С точки зрения производительности, как уже было указано в ответе @ nawfal,
Enum.GetName()
лучше.Если производительность действительно является вашей целью, то было бы еще лучше заранее выполнить поиск (используя словарь или другое сопоставление).
В C ++ / CLI это будет выглядеть так
Сравнение с использованием перечисления 100 элементов и 1000000 итераций:
источник
Просто: перечислить имена в список:
источник