2012-08-16 14 views
15

Esta pregunta se refiere a la fundición de las enumeraciones dentro de los métodos genéricosC# Fundición con objetos a enumeraciones

dado una enumeración

public enum Crustaceans 
{ 
    Frog = 1, 
    Toad = 4 
} 

que puedo crear una instancia de mi enumeración simplemente lo suficientemente

short val = 4; 
Crustaceans crusty = (Crustaceans) val; 

Sin embargo, si

short val = 4; 
object obj = (object) val; 
Crustaceans crusty = (Crustaceans)obj; 

se produce una excepción de tiempo de ejecución al intentar realizar la inicialización de crujiente.

¿Alguien puede explicar por qué esto sucede y por qué no es legal hacer tal cosa?

No es que realmente quisiera hacer esto, pero me topo con un problema cuando intento que algo similar ocurra con los genéricos y efectivamente eso es lo que sucede bajo las sábanas. es decir

public T dosomething<T>(short val) where T : new() 
{ 
    T result = (T)(object) val; 
    return result; 
} 

Así que lo que estoy tratando de hacer es tener una función genérica que trabaja con enumeraciones y no enumeraciones (no tan crítico, pero no estaría mal) que se puede ajustar a un valor corto sin lanzar una excepción y realmente inicializando el valor de enum correcto.

+21

¿Sería fuera de lugar señalar que la rana y el sapo no son crustáceos?:) – JTMon

+1

posible duplicado de [¿Por qué no puedo borrar un int como un decimal?] (Http://stackoverflow.com/questions/1085097/why-cant-i-unbox-an-int-as-a-decimal) –

+2

@sweetfa: si bien la pregunta que mencioné se refiere a int frente a decimal y no enumeraciones, explica el comportamiento (que está relacionado con el boxeo y el desempaquetado). En particular, la respuesta aceptada se refiere a un artículo de Eric Lippert: "[Representation and Identity] (http://blogs.msdn.com/b/ericlippert/archive/2009/03/19/representation-and-identity.aspx) ", lo cual explica esto en gran detalle. –

Respuesta

30

Algo como esto probablemente le ayudará a:

public T dosomething<T>(object o) 
{ 
    T enumVal= (T)Enum.Parse(typeof(T), o.ToString()); 
    return enumVal; 
} 

Pero esto va a funcionar única con enumeraciones, por una razón clara de la utilización de Enum.Parse(..)

Y utilizar esto como, por ejemplo:

object o = 4; 
dosomething<Crustaceans>(o); 

Eso devolverá Toad en su caso.

+1

Eso se puede arreglar rodeando el código con un cheque para que sea una enumeración o ; T pública dosomething (objeto o) {var enumType = typeof (T): un int igual que si (T está enumeración) –

+0

versión mejorada (?) if (! EnumType.IsEnum) throw new ArgumentException ("No es una enumeración"); return (T) Convert.ChangeType (o, enumType); } – osexpert

-1

Existen casos en los que no se pueden usar genéricos (como en un convertidor WPF cuando obtiene el valor como object). En este caso, no puede convertir a int porque el tipo de enumeración puede no ser int. Esta es una forma general de hacerlo sin genéricos. El ejemplo se da dentro de un WPF Converter, pero el código dentro es general:

using System; 
using System.Windows; 
using System.Windows.Data; 

. 
. 
. 

public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
{ 
    var enumType = value.GetType(); 
    var underlyingType = Enum.GetUnderlyingType(enumType); 
    var numericValue = System.Convert.ChangeType(value, underlyingType); 
    return numericValue; 
} 
0

Por valores de dígitos de enumeración defecto tienen type = int. En su código, desea convertir el valor que tiene tipo abreviado a tipo enum. Para eso, debes establecer el tipo abreviado a tus valores enum. Esto funcionará:

public enum Crustaceans : short // <-- 
{ 
    Frog = 1, 
    Toad = 4 
} 

short @short = 1; 
object @object = @short; 

var @enum = (Crustaceans)@object; // @enum = Crustaceans.Frog 

si no desea cambiar los valores por defecto de enumeración de tipo

public enum Crustaceans 
{ 
    Frog = 1, 
    Toad = 4 
} 

object @object = Crustaceans.Frog; 

var @enum = (Crustaceans)@object; // @enum = Crustaceans.Frog 

o

public enum Crustaceans 
{ 
    Frog = 1, 
    Toad = 4 
} 

int @integer= 1; 

var @enum = (Crustaceans)@integer; // @enum = Crustaceans.Frog