Перечисление в словарь
Я хочу реализовать метод расширения, который преобразует 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' не удалось найти (вы не видите используя директиву или сборку ссылка?)"
Ответы
Ответ 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 верен, я нашел, что это очень полезный метод расширения. Это не идеальный мир.