Как получить описание С# Enum из значения?

Возможный дубликат:
Получение атрибутов значения Enums

У меня есть перечисление с атрибутами Описание, как это:

public enum MyEnum
{
    Name1 = 1,
    [Description("Here is another")]
    HereIsAnother = 2,
    [Description("Last one")]
    LastOne = 3
}

Я нашел этот кусок кода для получения описания на основе Enum

public static string GetEnumDescription(Enum value)
{
    FieldInfo fi = value.GetType().GetField(value.ToString());

    DescriptionAttribute[] attributes = fi.GetCustomAttributes(typeof(DescriptionAttribute), false) as DescriptionAttribute[];

    if (attributes != null && attributes.Any())
    {
        return attributes.First().Description;
    }

    return value.ToString();
}

Это позволяет мне писать код как:

var myEnumDescriptions = from MyEnum n in Enum.GetValues(typeof(MyEnum))
                         select new { ID = (int)n, Name = Enumerations.GetEnumDescription(n) };

Что я хочу сделать, если я знаю значение перечисления (например, 1) - как я могу получить описание? Другими словами, как я могу преобразовать целое число в "значение Enum" для передачи в мой метод GetDescription?

Ответ 1

int value = 1;
string description = Enumerations.GetEnumDescription((MyEnum)value);

Основной тип данных по умолчанию для enum в С# - int, вы можете просто его отличить.

Ответ 2

Обновить

Библиотека Unconstrained Melody больше не поддерживается; Поддержка была прекращена в пользу Enums.NET.

В Enums.NET вы бы использовали:

string description = ((MyEnum)value).AsString(EnumFormat.Description);

Оригинальный пост

Я реализовал это в общем, безопасном для типов виде в Мелодии без ограничений - вы бы использовали:

string description = Enums.GetDescription((MyEnum)value);

Это:

  • Гарантирует (с ограничениями универсального типа), что значение действительно является значением перечисления
  • Избегает бокса в вашем текущем решении
  • Кэширует все описания, чтобы не использовать отражения при каждом вызове.
  • Имеет кучу других методов, в том числе возможность разобрать значение из описания

Я понимаю, что основной ответ был просто приведением от int к MyEnum, но если вы выполняете много работы с перечислениями, стоит подумать об использовании Unconstrained Melody :)

Ответ 3

Я поместил код из принятого ответа в общий метод расширения, поэтому его можно было использовать для всех видов объектов:

public static string DescriptionAttr<T>(this T source)
{
    FieldInfo fi = source.GetType().GetField(source.ToString());

    DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(
        typeof(DescriptionAttribute), false);

    if (attributes != null && attributes.Length > 0) return attributes[0].Description;
    else return source.ToString();
}

Используя перечисление, как в исходном сообщении, или любой другой класс, свойство которого украшено атрибутом Description, код может быть использован следующим образом:

string enumDesc = MyEnum.HereIsAnother.DescriptionAttr();
string classDesc = myInstance.SomeProperty.DescriptionAttr();

Ответ 4

Чтобы сделать это проще в использовании, я написал общее расширение:

public static string ToDescription<TEnum>(this TEnum EnumValue) where TEnum : struct
{
    return Enumerations.GetEnumDescription((Enum)(object)((TEnum)EnumValue));
}

теперь я могу написать:

        MyEnum my = MyEnum.HereIsAnother;
        string description = my.ToDescription();
        System.Diagnostics.Debug.Print(description);

Примечание: замените "Перечисления" выше на ваше имя класса

Ответ 5

Вы не можете легко сделать это в общем виде: вы можете преобразовать целое число в определенный тип перечисления. Как показал Николас, это тривиальный бросок, если вы только заботитесь об одном виде перечисления, но если вы хотите написать общий метод, который может обрабатывать различные виды перечислений, все становится немного сложнее. Вам нужен метод по строкам:

public static string GetEnumDescription<TEnum>(int value)
{
  return GetEnumDescription((Enum)((TEnum)value));  // error!
}

но это приводит к ошибке компилятора, что "int не может быть преобразовано в TEnum" (и если вы обойдете это, то "TEnum не может быть преобразован в Enum" ). Поэтому вам нужно обмануть компилятор, вставив приведение в объект:

public static string GetEnumDescription<TEnum>(int value)
{
  return GetEnumDescription((Enum)(object)((TEnum)(object)value));  // ugly, but works
}

Теперь вы можете вызвать это, чтобы получить описание любого типа перечисления:

GetEnumDescription<MyEnum>(1);
GetEnumDescription<YourEnum>(2);