2010-11-04 5 views
7

Я уверен, что это довольно тривиально, но я не могу понять это правильно.Установите значение enum на значение по умолчанию

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 
} 

Линия value = default(value.GetType()); не обобщать, но, надеюсь, вы можете увидеть, что я пытаюсь. Мне нужно установить параметр Enum для значения по умолчанию его собственного типа.

+0

Как может вы даже называете этот метод без определения значения в перечислении того же типа, что и «значение»? –

+0

@Paw, вот как работает enum. Вы можете сохранить любое значение int в int enum, независимо от того, определено оно или нет. – fearofawhackplanet

+0

@fearofawhackplanet, я просто пытаюсь понять, что вы пытаетесь сделать. Если вы хотите преобразовать int в перечисление или, может быть, строку в перечисление? –

ответ

1

Activator.CreateInstance(typeof(ConsoleColor)), кажется, работает

+0

Для этого вам нужен жесткий бросок. (ConsoleColor) Activator.CreateInstance (typeof (ConsoleColor)) –

+0

@Paw, как бы вы это делали в примере страха (с динамическим типом) –

+0

вы не можете, поэтому я не думаю, что он будет работать с Activator. –

-1

Enum по умолчанию имеют свои first value в default value

+3

снова, как это решает мою проблему? (и это даже не технически правильно, я не думаю) – fearofawhackplanet

+2

-1: Извините, но значение по умолчанию для каждого перечисления равно 0, даже если 0 является недопустимым значением для перечисления. Попробуйте 'enum MyEnum {M1 = -1, M2 = 1}; MyEnum e = default (MyEnum); ... Console.WriteLine ("{0}", e); 'Writes' 0' –

-1

Вы думали о том, что общий метод?

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

Вызывающий метод должен знать тип.

+3

'где T: enum' не существует в C#. :-(Вот и вся проблема здесь. –

+0

Ах, правда, удалил это. –

+0

По-прежнему будет работать, но без «где». Вам просто нужно попробовать/поймать, чтобы убедиться, что ваш бросок не взорвется. вызывать новое исключение для вызывающего, если T не было перечислением. –

5

Я не совсем уверен, что вы пытаетесь сделать здесь, но версия линии «по умолчанию», который делает компиляции заключается в следующем:

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

Или, даже чище (от Paw, в комментарии, спасибо):

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

Это вторая версия делает только работать должным образом, если вы знаете, первый элемент перечисления имеет нулевое значение.

+0

или value = (Enum) Enum.ToObject (value.GetType(), 0); –

+0

@paw Что делать, re используя это: 'enum Foo {a = 1, b = 2}'? +1 to Will, хотя он выглядит довольно уверенно –

+0

@Paw: № 0 не является определенным значением для всех перечислений. –

2

Вы на самом деле могли бы сделать то, что Paw is suggesting, даже с общим ограничением, если вы могли бы переместить этот метод к своему собственному классу:

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> { } 

Тогда вы могли бы сделать, например:

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 

Как отмечает Конрад Рудольф в комментарии, default(TEnum) в приведенном выше коде будет оцениваться до 0, независимо от того, определено или нет значение для 0 для данного типа TEnum. Если это не то, что вы хотите, Will's answer обеспечивает, безусловно, самый простой способ получения первого значения ((TEnum)Enum.GetValues(typeof(TEnum)).GetValue(0)).

С другой стороны, если вы хотите принять это к крайней и кэшировать результат, так что вы не всегда должны боксировать, вы могли бы сделать это:

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

Ваш код не компилируется для меня (Mono C#). –

+0

@ Konrad: Это может быть потому, что у меня была опечатка ('TEnumvalue'-no space). Также я не включил возвращаемое значение. Мне было бы интересно узнать, скомпилирует ли он сейчас Mono, что я обновил этот пример. –

+0

Я уже исправил это, не помогло. Странно, теперь он компилирует (+1, изящный хак!) - но он имеет ту же проблему, что и другие решения, а именно: 'default' действительно возвращает' 0', который может быть неопределенным значением в фактическом перечислении и, следовательно, не является правильный результат. Есть дополнительная проблема, что ваше решение больше не работает как метод расширения. –

Смежные вопросы