Подтвердить что ты не робот

Перечисление в словарь

Я хочу реализовать метод расширения, который преобразует enum в словарь.

public static Dictionary<int, string> ToDictionary(this Enum @enum)
            {
                Type type1 = @enum.GetType();
                return Enum.GetValues(type1).Cast<type1>()
                    //.OfType<typeof(@enum)>()
                    .ToDictionary(e => Enum.GetName(@enum.GetType(), e));
            }

Почему он не компилируется?

Ошибка

"Тип или имя пространства имен 'type1' не удалось найти (вы не видите используя директиву или сборку ссылка?)"

4b9b3361

Ответ 1

Джон Скит написал все, что вам нужно;)

Но здесь у вас есть свой код, который работает:

public static Dictionary<int, string> ToDictionary(this Enum @enum)
{
  var type = @enum.GetType();
  return Enum.GetValues(type).Cast<int>().ToDictionary(e => e, e => Enum.GetName(type, e));
}

Ответ 2

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

Вы можете сделать это с отражением, но было бы лучше сделать его универсальным методом. К сожалению, вы не можете ограничить параметр типа generic как enum, хотя у меня есть некоторые хаки, которые можно обойти, в Unconstrained Melody.

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

Теперь следующая проблема заключается в том, что вы пытаетесь получить Dictionary<int, string>, но значения перечисления не являются значениями int. Они могут быть преобразованы в значения int, но они не могут быть немедленно отправлены. Вы можете использовать Convert.ToInt32 для этого, но вам нужно что-то сделать.

Наконец (на данный момент), что вы ожидали бы с перечислением с использованием базового типа uint или long?

Ответ 3

Вы не можете использовать type1 как общий параметр, потому что это переменная, а не тип.

Следующий код делает что-то похожее на то, что показывает ваш код:

public static Dictionary<string, TEnum> ToDictionary<TEnum>()
    where TEnum : struct
{
    if (!typeof(TEnum).IsEnum)
        throw new ArgumentException("Type must be an enumeration");
    return Enum.GetValues(typeof(TEnum)).Cast<TEnum>().
            ToDictionary(e => Enum.GetName(typeof(TEnum), e));
}

Используйте его следующим образом:

ToDictionary<Colors>()

Но я не уверен, это то, что вы ожидали?
Кроме того, у него есть одна проблема: вы можете передать любую структуру, а не только перечисления, и это приведет к исключению во время выполнения. См. Ответ Джона для получения более подробной информации об этом.

Ответ 4

На основе решения Daniel

public static SelectList ToSelectList<TEnum>(this HtmlHelper h) where TEnum : struct
{
 return new SelectList(FortunaExtension.ToDictionary<TEnum>(), "Key", "Value");
}

Ответ 5

Вот метод расширения, который я использую для преобразования перечислений, только разница в том, что я возвращаю IEnumerbale > для своей цели:

public static IEnumerable<KeyValuePair<int, string>> ToListOfKeyValuePairs<TEnum>(this TEnum enumeration) where TEnum : struct
{
    return from TEnum e in Enum.GetValues(typeof(TEnum))
            select new KeyValuePair<int, string>
                (
                    (int)Enum.Parse(typeof(TEnum), e.ToString()),
                    Regex.Replace(e.ToString(), "[A-Z]", x => string.Concat(" ", x.Value[0])).Trim()
                );
}

Он также добавляет пробелы для значения.

Пример:

enum Province
{
    BritishColumbia = 0,
    Ontario = 1
}

Использование:

<select>
<% foreach(var item in Province.BritishColumbia.ToListOfKeyValuePairs()){ %>
    <option value="<%=item.Key %>"><%=item.Value %></option>
<% } %>
</select>

Вывод:

<select>
    <option value="0">British Columbia</option>
    <option value="1">Ontario</option>
</select>

Хотя @Paul Ruane верен, я нашел, что это очень полезный метод расширения. Это не идеальный мир.