Установите для перечисления значение по умолчанию - PullRequest
7 голосов
/ 04 ноября 2010

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

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 значение по умолчанию его собственного типа.

Ответы [ 5 ]

5 голосов
/ 04 ноября 2010

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

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

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

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

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

2 голосов
/ 04 ноября 2010

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

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,Если это не то, что вам нужно, ответ Уилла , безусловно, обеспечивает самый простой способ получения первого определенного значения ((TEnum)Enum.GetValues(typeof(TEnum)).GetValue(0)).

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

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;
    }
}
1 голос
/ 04 ноября 2010

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

0 голосов
/ 04 ноября 2010

Задумывались ли вы о том, чтобы сделать его универсальным методом?

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

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

0 голосов
/ 04 ноября 2010

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

...