Який найкращий спосіб перетворити Enum у String в .NET 3.5?
- Enum.GetName
- Enum.Format
- ToString
Чому я віддаю перевагу одному з таких перед іншими? Чи працює краще?
Який найкращий спосіб перетворити Enum у String в .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()
перетворити перерахування в рядок. Натомість використовуйте оператор перемикання, а також, якщо потрібно, інтернаціоналізуйте імена.
Enum.GetName()
Format()
насправді просто обгортка GetName()
з деяким функціонуванням форматування (або InternalGetValueAsString()
якщо бути точним). ToString()
майже все те саме, що Format()
. Я думаю GetName()
, що найкращий варіант, оскільки абсолютно очевидно, що це робить для тих, хто читає джерело.
Я створюю метод розширення "Опис" і прикріплюю його до перерахунку, щоб я міг отримати справді зручну назву, яка включає пробіли та корпуси. Мені ніколи не подобалося використовувати саме значення 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