Какой предпочтительный способ преобразовать 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