Как получить строковое представление перечисления (Enum) в C#? Проблема с ToString()
Решение: стандартные методы и кастомная кастомизация через атрибуты
В C# есть несколько способов получить строковое представление enum, и выбор зависит от того, что именно вам нужно: имя константы, числовое значение или кастомная строка. Давайте разберём все варианты от простых к сложным.
1. Базовые методы: ToString() и Enum.GetName()
По умолчанию ToString() возвращает имя константы (например, "Success"). Это работает для всех enum. Enum.GetName() делает то же самое, но требует явного указания типа:
StatusCode status = StatusCode.NotFound;
string name = status.ToString(); // "NotFound"
string name2 = Enum.GetName(typeof(StatusCode), status); // "NotFound"
2. Получение числового значения
Если нужно числовое значение в виде строки, используйте приведение к базовому типу (обычно int):
string intValue = ((int)status).ToString(); // "404"
Это самый быстрый и простой способ, но он не подходит, если нужно получить что-то более осмысленное.
3. Кастомные строки с атрибутом Description
Для человекочитаемых строк с пробелами или другими символами используйте атрибут [Description] из пространства имён System.ComponentModel. Это стандартный подход в .NET:
using System.ComponentModel;
public enum StatusCode
{
[Description("Успешный ответ")]
Success = 200,
[Description("Не найдено")]
NotFound = 404,
[Description("Ошибка сервера")]
ServerError = 500
}
// Метод для получения Description
public static string GetEnumDescription(Enum value)
{
var field = value.GetType().GetField(value.ToString());
var attribute = field.GetCustomAttributes(typeof(DescriptionAttribute), false)
.FirstOrDefault() as DescriptionAttribute;
return attribute == null ? value.ToString() : attribute.Description;
}
// Использование
StatusCode status = StatusCode.NotFound;
string description = GetEnumDescription(status); // "Не найдено"
4. Атрибут DisplayAttribute для локализации
Если нужно поддерживать несколько языков, используйте [Display] из System.ComponentModel.DataAnnotations. Он поддерживает ресурсы для локализации:
using System.ComponentModel.DataAnnotations;
public enum StatusCode
{
[Display(Name = "Success", ResourceType = typeof(Resources))]
Success = 200,
[Display(Name = "NotFound", ResourceType = typeof(Resources))]
NotFound = 404
}
// Метод получения Display Name
public static string GetDisplayName(Enum value)
{
var field = value.GetType().GetField(value.ToString());
var attribute = field.GetCustomAttributes(typeof(DisplayAttribute), false)
.FirstOrDefault() as DisplayAttribute;
return attribute?.GetName() ?? value.ToString();
}
5. Универсальный метод с рефлексией (Extension Method)
Для удобства можно создать extension-метод, который будет работать с любым enum:
public static class EnumExtensions
{
public static string ToDescriptionString(this Enum value)
{
var field = value.GetType().GetField(value.ToString());
var attr = field.GetCustomAttributes(typeof(DescriptionAttribute), false)
.FirstOrDefault() as DescriptionAttribute;
return attr == null ? value.ToString() : attr.Description;
}
}
// Использование
string desc = StatusCode.Success.ToDescriptionString(); // "Успешный ответ"
6. Альтернатива: словарь или switch (без рефлексии)
Если производительность критична, избегайте рефлексии. Используйте словарь или switch:
public static string GetStatusString(StatusCode status)
{
return status switch
{
StatusCode.Success => "Успех",
StatusCode.NotFound => "Не найдено",
StatusCode.ServerError => "Ошибка сервера",
_ => status.ToString()
};
}
Итог:
- Для простых имён —
ToString(). - Для чисел —
((int)enum).ToString(). - Для кастомных строк с пробелами/локализацией —
[Description]или[Display]. - Для максимальной производительности — switch или словарь.
Выберите подход, который лучше всего подходит под вашу задачу. В большинстве бизнес-приложений достаточно атрибута [Description].
Дополнение: Enum.ToString() с флагами и Format-спецификаторы
В .NET есть встроенные format-спецификаторы для enum, которые могут быть полезны в некоторых сценариях. Метод ToString(string format) принимает следующие значения:
"G"или"g"— имя константы (по умолчанию)."D"или"d"— числовое значение в десятичной системе."X"— числовое значение в шестнадцатеричной системе."F"— для enum с атрибутом[Flags]выводит комбинацию имён.
Примеры:
[Flags]
public enum Permissions
{
None = 0,
Read = 1,
Write = 2,
Execute = 4
}
Permissions perms = Permissions.Read | Permissions.Write;
Console.WriteLine(perms.ToString("G")); // "Read, Write"
Console.WriteLine(perms.ToString("D")); // "3"
Console.WriteLine(perms.ToString("X")); // "3"
Обратите внимание: для обычных enum (без [Flags]) спецификатор "F" работает так же, как "G". А "D" — это самый простой способ получить числовое значение без приведения к int. Это удобно для логирования или сериализации.
Также помните, что для enum с флагами ToString() по умолчанию использует "G", но если значение не соответствует ни одной комбинации флагов, он вернёт число. Это поведение может быть неочевидным, поэтому для флаговых enum лучше всегда явно указывать формат.
Ответов пока нет.
Войдите чтобы оставить ответ
Блоги