2011-03-31 10 views
26

Deseo implementar el método de extensión, que convierte enum en diccionario.Enum al diccionario

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)); 
      } 

¿Por qué no compila?

un error

"El tipo o espacio de nombres 'tipo1' no se pudo encontrar (¿falta una directiva using o un conjunto referencia?)"

+2

¿Por qué no nos muestran el mensaje de error? –

Respuesta

48

Jon Skeet has written everything you need;)

Pero aquí tienes tu código que está trabajando:

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)); 
} 
+0

Sí, es bueno! – Alexandre

+1

Puede simplificarlo ligeramente escribiendo 'Transmitir 'en lugar de' Transmitir ', porque entonces puede omitir la conversión de objeto a int en la primera expresión lambda. –

+0

Sí, tienes razón :) Buenos consejos :) Thx –

4

Puede No use type1 como parámetro genérico, porque es una variable, no un tipo.

El siguiente código hace algo similares a lo que muestra su código:

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)); 
} 

utilizar de esta manera:

ToDictionary<Colors>() 

pero no estoy realmente seguro, esto es, lo que se esperaba ?
Además, tiene un problema: puede pasar cualquier estructura, no solo enumeraciones y esto dará lugar a una excepción de tiempo de ejecución. Ver la respuesta de Jon para más detalles sobre eso.

+0

No es lo que espero. Quiero usar el método de extensión. – Alexandre

+0

Muestre un ejemplo de código de su uso y el resultado esperado. (Debido a que no parece tener sentido invocar esto como un método de extensión) –

+1

@Alex Maslakov: un método de extensión no es realmente apropiado aquí ya que está construyendo un diccionario a partir de los datos sobre la enumeración que está disponible estáticamente (es decir, son los datos en la definición del tipo de enumeración en lugar de usar las propiedades de un valor enum particular). Los métodos de extensión operan en una instancia de un tipo. –

12

Bueno, está intentando usar una variable del tipo Type como un argumento de tipo genérico. No se puede hacer eso con genéricos, que son aproximadamente en tiempo de compilación tipos.

Puede hacerlo con reflexión, pero sería mejor hacerlo un método genérico. Lamentablemente, no puede restringir un parámetro de tipo genérico para ser una enumeración, aunque tengo algunos hacks para solucionarlo en Unconstrained Melody.

En caso de que esto suceda, puede usar solo una restricción de tipo struct para un método genérico que sería un buen comienzo.

Ahora, el siguiente problema es que usted está tratando de conseguir un Dictionary<int, string> - pero los valores de una enumeración no es int valores. Pueden ser convertibles a int valores, pero no están allí inmediatamente. Puede usar Convert.ToInt32 para hacer eso, pero tendría que hacer algo.

Finalmente (por el momento) ¿qué esperarías que ocurriera con una enumeración usando un tipo subyacente uint o long?

1

Aquí es el método de extensión que utilizo para convertir las enumeraciones, única diferencia es que estoy volviendo IEnumerbale> para mi propósito:

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() 
       ); 
} 

También agrega espacios para el valor.

Ejemplo:

enum Province 
{ 
    BritishColumbia = 0, 
    Ontario = 1 
} 

Uso:

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

de salida:

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

Aunque @ Pablo Ruane es correcta he encontrado que esto es un método de extensión muy útil. No es un mundo perfecto.

2

basado en la solución de Daniel

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