Какой предпочтительный способ преобразовать Enum в строку в .NET 3.5?
- Enum.GetName
- Enum.Format
- Нанизывать
Почему я должен предпочесть один из них другим? Работает ли лучше?
Какой предпочтительный способ преобразовать Enum в строку в .NET 3.5?
Почему я должен предпочесть один из них другим? Работает ли лучше?
Ответы:
Начиная с C # 6, лучший способ получить имя перечисления - это новый nameof
оператор:
nameof(MyEnum.EnumValue);
// Ouputs
> "EnumValue"
Это работает во время компиляции, при этом перечисление заменяется строкой в скомпилированном результате, что, в свою очередь, означает, что это самый быстрый возможный способ.
Любое использование имен enum мешает запутыванию кода, если вы считаете, что запутывание имен enum стоит или важно - это, вероятно, совсем другой вопрос.
nameof(variableEnum)
будет "variableEnum"
. Он отражает (во время сборки) имя поля / свойства / параметра / переменной, а не значение .
"someEnumValue"
, а вам нужно nameof(SomeEnum.FooBar)
получить "FooBar"
.
Работает для нашего проекта ...
public static String convertToString(this Enum eff)
{
return Enum.GetName(eff.GetType(), eff);
}
public static EnumType converToEnum<EnumType>(this String enumValue)
{
return (EnumType) Enum.Parse(typeof(EnumType), enumValue);
}
В моих тестах Enum.GetName
был быстрее и с приличным запасом. Внутренние ToString
звонкиEnum.GetName
. Из источника для .NET 4.0, основы:
public override String ToString()
{
return Enum.InternalFormat((RuntimeType)GetType(), GetValue());
}
private static String InternalFormat(RuntimeType eT, Object value)
{
if (!eT.IsDefined(typeof(System.FlagsAttribute), false))
{
String retval = GetName(eT, value); //<== the one
if (retval == null)
return value.ToString();
else
return retval;
}
else
{
return InternalFlagsFormat(eT, value);
}
}
Не могу сказать, что в этом причина, но тесты показывают, что один быстрее другого. Оба вызова включают в себя бокс (на самом деле это вызовы отражения, вы, по сути, извлекаете имена полей) и могут быть медленными по вашему вкусу.
Испытательная установка : перечисление с 8 значениями, нет. итераций = 1000000
Результат : Enum.GetName => 700 мс, ToString => 2000 мс
Если скорость не заметна, я бы не заботился и не использовал ToString
так как она предлагает более чистый вызов. Контраст
Enum.GetName(typeof(Bla), value)
с участием
value.ToString()
Это самый элегантный метод, который предназначен для этого.
var enumValueString = Enum.GetName(typeof (MyEnum), MyEnum.MyValue);
Хотя я не вижу никаких проблем с вызовом, так .ToString()
как он просто короче.
var enumValueString = MyEnum.MyValue.ToString();
С новым синтаксисом C # 6 вы можете использовать:
nameof(MyEnum.MyValue)
Все это внутренне вызывает вызов метода InternalGetValueAsString
. Разница между ToString
и GetName
будет в том, что GetName
сначала нужно проверить несколько вещей:
GetType
значение, чтобы проверить это..ToString
не нужно беспокоиться ни об одной из перечисленных выше проблем, поскольку он вызывается для экземпляра самого класса, а не для переданной версии, поэтому из-за того, что .ToString
метод не имеет таких же проблем проверки в качестве статических методов я бы заключил, что.ToString
это самый быстрый способ получить значение в виде строки.
Лучшее, что я могу найти, - это не связанный вопрос на MSDN , который содержит фрагмент XML, который отвечает на этот вопрос. Любой из этих методов имеет один и тот же недостаток: они вызывают enum.toString()
, что не работает должным образом при использовании Dotfuscation . Другие проблемы, по-видимому, связаны с косвенным боксом (GetName и Format). К сожалению, я не могу найти никаких причин производительности для использования любого из вышеперечисленного.
Перефразируя из фрагмента XML ,
Передача перечисленного в штучной упаковке перечисления в string.Format () или любую другую функцию может привести к вызову
enum.ToString()
. Это вызовет проблемы при расфокусировке. Вы не должны использоватьenum.ToString()
,enum.GetNames()
,enum.GetName()
,enum.Format()
илиenum.Parse()
преобразовать перечисление в строку. Вместо этого используйте оператор switch, а также при необходимости интернационализируйте имена.
Enum.GetName()
Format()
на самом деле просто обертка GetName()
с некоторыми функциями форматирования (или, InternalGetValueAsString()
если быть точным). ToString()
в значительной степени так же , как Format()
. Я думаю, что GetName()
это лучший вариант, поскольку совершенно очевидно, что он делает для тех, кто читает источник.
Я создаю метод расширения «Description» и присоединяю его к перечислению, чтобы получить действительно удобное для пользователя наименование, включающее пробелы и регистр. Мне никогда не нравилось использовать само значение enum в качестве отображаемого текста, потому что это то, что мы разработчики используем для создания более читабельного кода. Он не предназначен для отображения пользовательского интерфейса. Я хочу иметь возможность изменять пользовательский интерфейс, не проходя и не меняя перечисления во всем.
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 итераций:
Enum.GetName: ~ 800ms
.ToString (): ~ 1600ms
Отображение словаря: ~ 250ms