2010-11-04 17 views
7

Jestem pewien, że jest to dość banalne, ale nie mogę tego naprawić.Ustaw wyliczenie na domyślną wartość

public static string DoSomething(this Enum value) 
{ 
    if (!Enum.IsDefined(value.GetType(), value)) 
    { 
     // not a valid value, assume default value 
     value = default(value.GetType()); 
    } 

    // ... do some other stuff 
} 

Linia value = default(value.GetType()); nie kompiluje, ale mam nadzieję, że można zobaczyć, co mam próby. Muszę ustawić parametr Enum na domyślną wartość jego własnego typu.

+0

Jak można nazywasz tę metodę nawet bez zdefiniowania "wartości" w wyliczeniu tego samego typu co "wartość"? –

+0

@Paw, w ten sposób działa enum. Możesz przechowywać dowolną wartość int w int enum, bez względu na to, czy jest zdefiniowana, czy nie. – fearofawhackplanet

+0

@fearofawhackplanet, próbuję tylko zrozumieć, co próbujesz zrobić. Jeśli chcesz przekonwertować int do enum, a może string na wyliczenie? –

Odpowiedz

1

Activator.CreateInstance(typeof(ConsoleColor)) wydaje się działać

+0

Potrzebujesz do tego ciężkiej obsady. (ConsoleColor) Activator.CreateInstance (typeof (ConsoleColor)) –

+0

@Paw, jak byś to zrobił w przykładzie strachu (z dynamicznym typem) –

+0

nie możesz, dlatego nie sądzę, że będzie działać z Activatorem. –

-1

Enum domyślnie mieć first value jak default value

+3

ponownie, jak to rozwiązuje mój problem? (i to nawet nie jest technicznie poprawne, nie sądzę) – fearofawhackplanet

+2

-1: Niestety, ale domyślna wartość dla każdego wyliczenia wynosi 0, nawet jeśli 0 jest nieprawidłową wartością dla wyliczenia. Wypróbuj 'enum MyEnum {M1 = -1, M2 = 1}; MyEnum e = default (MyEnum); ... Console.WriteLine ("{0}", e); 'Zapisuje' 0' –

-1

Czy myślałeś o zrobieniu to metoda rodzajowa?

public static string DoSomething<T>(Enum value) 
{ 
    if (!Enum.IsDefined(typeof(T), value)) 
    { 
     value = (T)Enum.ToObject(typeof(T), 0); 
    } 
    // ... do some other stuff 
} 

Osoba wywołująca metodę powinna znać typ.

+3

'where T: enum' nie istnieje w języku C#. :-(To jest cały problem tutaj –

+0

Ah true, usunięto to. –

+0

Mimo to nadal działałbym, bez "miejsca" .Potrzebowałbyś/chciałbyś, aby twoja obsada nie wysadziła się. wyrzuć nowy wyjątek do rozmówcy, jeśli T nie jest wylicznikiem –

5

Nie jestem pewien, co starasz się zrobić tutaj, ale to wersja „default” linii, która dokłada skompilować to:

value = (Enum)Enum.GetValues(value.GetType()).GetValue(0); 

Albo nawet czystsze (od Paw, w komentarze, dzięki):

value = (Enum) Enum.ToObject(value.GetType(), 0); 

Ta druga wersja nie działa prawidłowo tylko, jeśli wiesz, pierwszy element wyliczenia ma wartość zero.

+0

lub wartość = (Enum) Enum.ToObject (value.GetType(), 0); –

+0

@paw Co jeśli" Ponownie użyj tego: 'enum Foo {a = 1, b = 2}'? +1 do woli, ale wygląda całkiem solidnie –

+0

@Paw: Nr 0 nie jest zdefiniowaną wartością dla wszystkich wyliczeń –

2

rzeczywiście może zrobić co Paw is suggesting, nawet z rodzajowe ograniczeń, jeśli można przenieść tę metodę do swojej klasie:

public abstract class Helper<T> 
{ 
    public static string DoSomething<TEnum>(TEnum value) where TEnum: struct, T 
    { 
     if (!Enum.IsDefined(typeof(TEnum), value)) 
     { 
      value = default(TEnum); 
     } 

     // ... do some other stuff 

     // just to get code to compile 
     return value.ToString(); 
    } 
} 

public class EnumHelper : Helper<Enum> { } 

Wtedy ty, na przykład:

MyEnum x = MyEnum.SomeValue; 
MyEnum y = (MyEnum)100; // Let's say this is undefined. 

EnumHelper.DoSomething(x); // generic type of MyEnum can be inferred 
EnumHelper.DoSomething(y); // same here 

Jak zaznacza Konrad Rudolph w komentarzu, default(TEnum) w powyższym kodzie oceni na 0, niezależnie od tego, czy wartość jest zdefiniowana dla 0 dla danego typu TEnum. Jeśli to nie jest to, czego chcesz, Will's answer zapewnia z pewnością najłatwiejszy sposób uzyskania pierwszej wartości zdefiniowanej jako().

Z drugiej strony, jeśli chcesz wziąć to do skrajnego i buforować wynik tak, że nie zawsze musi to pole, można to zrobić:

public abstract class Helper<T> 
{ 
    static Dictionary<Type, T> s_defaults = new Dictionary<Type, T>(); 

    public static string DoSomething<TEnum>(TEnum value) where TEnum: struct, T 
    { 
     if (!Enum.IsDefined(typeof(TEnum), value)) 
     { 
      value = GetDefault<TEnum>(); 
     } 

     // ... do some other stuff 

     // just to get code to compile 
     return value.ToString(); 
    } 

    public static TEnum GetDefault<TEnum>() where TEnum : struct, T 
    { 
     T definedDefault; 
     if (!s_defaults.TryGetValue(typeof(TEnum), out definedDefault)) 
     { 
      // This is the only time you'll have to box the defined default. 
      definedDefault = (T)Enum.GetValues(typeof(TEnum)).GetValue(0); 
      s_defaults[typeof(TEnum)] = definedDefault; 
     } 

     // Every subsequent call to GetDefault on the same TEnum type 
     // will unbox the same object. 
     return (TEnum)definedDefault; 
    } 
} 
+0

Twój kod nie kompiluje się dla mnie (Mono C#). –

+0

@Konrad: To * może * być, ponieważ miałem w nim literówkę ("TEnumvalue" - brak spacji). Również nie zawarłem wartości zwracanej. Byłbym ciekawy, czy kompiluje się dla Mono teraz, gdy zaktualizowałem ten przykład. –

+0

Już to poprawiłem, nie pomogłem. Dziwnie, teraz kompiluje (+1, elegancki hack!) - ale ma ten sam problem co inne rozwiązania, a mianowicie, że 'default' naprawdę zwraca' 0', co może być niezdefiniowaną wartością w rzeczywistym wyliczeniu, a zatem nie jest odpowiedni wynik. Istnieje dodatkowy problem, że Twoje rozwiązanie nie działa już jako metoda rozszerzenia. –