2012-08-16 10 views
15

Diese Frage Aufzählungen betrifft Gießen von Aufzählungen innerhalb generischen MethodenC# Casting mit Objekten

eine Enumeration

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

ich eine Instanz meiner Enum erstellen kann einfach genug gegeben

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

Wenn jedoch

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

wird eine Laufzeitausnahme ausgelöst, die versucht, die Initialisierung von Crusty durchzuführen.

Kann jemand erklären, warum dies geschieht, und warum es nicht legal ist, so etwas zu tun.

Nicht, dass ich das wirklich tun wollte, aber ich habe ein Problem, wenn ich versuche, etwas Ähnliches mit Generika zu erreichen und effektiv ist das, was unter der Decke passiert. dh

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

Also, was ich bin versucht, eine generische Funktion zu tun ist, die mit Aufzählungen und nicht-Aufzählungen arbeitet (nicht so kritisch, aber schön wäre), die ohne Auslösen einer Ausnahme auf einen kurzen Wert eingestellt werden kann, und tatsächlich den korrekten Enum-Wert initialisiert.

+21

Typ verändern Wäre es aus der Linie darauf hinweisen, dass Frosch und Kröte sind nicht Krebstiere?:) – JTMon

+1

möglich Duplikat von [Warum kann ich nicht ein int als Dezimaltrennzeichen ausgeben?] (Http://stackoverflow.com/questions/1085097/why-cant-i-unbox-an-int-as-a-decimal) –

+2

@sweetfa: während die Frage, auf die ich hingewiesen habe, sich mit int vs. dezimal und nicht enums befasst, erklärt es das Verhalten (das mit Boxen und Unboxing zusammenhängt). Insbesondere bezieht sich die angenommene Antwort auf einen Artikel von Eric Lippert: "[Repräsentation und Identität] (http://blogs.msdn.com/b/ericlippert/archive/2009/03/19/representation-and-identity.aspx) ", was dies sehr detailliert erklärt. –

Antwort

30

So etwas wie diese wahrscheinlich werden Ihnen helfen:

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

Aber das wird nur mit Aufzählungen arbeiten, für klaren Grund von Enum.Parse(..)

mit Und wie, zum Beispiel:

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

Das wird Toad in zurückkehren Ihr Fall.

+1

Das kann behoben werden, indem man den Code mit einem Häkchen umgibt, damit es ein enum oder ist ein int wie so if (T enum) –

+0

Verbesserte Version (?): public T dosomething (object o) { var enumType = typeof (T); if (! EnumType.IsEnum) Neue ArgumentException werfen ("Not a enum"); Rückgabe (T) Convert.ChangeType (o, enumType); } – osexpert

-1

Es gibt Fälle, in denen Sie Generics nicht verwenden können (wie in einem WPF-Konverter, wenn Sie den Wert als object erhalten). In diesem Fall können Sie nicht in int umwandeln, da der Enum-Typ kein int sein darf. Dies ist ein allgemeiner Weg ohne Generics. Das Beispiel ist in einem WPF-Konverter gegeben, aber der Code innerhalb ist allgemein:

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

standardmäßig Enum stelligen Werte type = int haben. In Ihrem Code möchten Sie einen Wert übergeben, der einen kurzen Typ zum Aufzählungstyp hat. Dafür müssen Sie einen kurzen Typ auf Ihre Enum-Werte setzen. Dies funktioniert:

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

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

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

wenn Sie wollen Standard ENUM-Werte nicht

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

object @object = Crustaceans.Frog; 

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

oder

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

int @integer= 1; 

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