2010-11-04 5 views
7

Je suis sûr que c'est assez trivial mais je ne peux pas le faire correctement.Définir un enum à sa valeur par défaut

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 
} 

La ligne value = default(value.GetType()); ne compile pas, mais nous espérons que vous pouvez voir ce que je tente. Je dois définir le paramètre Enum à la valeur par défaut de son propre type.

+0

Comment vous appelez même cette méthode sans que la 'valeur' ​​ne soit définie dans l'énumération du même type que 'valeur'? –

+0

@Paw, c'est ainsi que fonctionne Enum. Vous pouvez stocker n'importe quelle valeur int dans un entier, qu'il soit défini ou non. – fearofawhackplanet

+0

@fearofawhackplanet, j'essaie juste de comprendre ce que vous essayez de faire. Si vous voulez convertir un int en enum ou peut-être une chaîne enum? –

Répondre

1

Activator.CreateInstance(typeof(ConsoleColor)) semble fonctionner

+0

Vous avez besoin d'une distribution solide pour cela. (ConsoleColor) Activator.CreateInstance (typeof (ConsoleColor)) –

+0

@Paw, comment le feriez-vous dans l'exemple de la peur (avec un type dynamique) –

+0

vous ne pouvez pas, c'est pourquoi je ne pense pas que cela fonctionnera avec Activator. –

-1

Enum par défaut ont son first value comme default value

+3

encore une fois, comment cela résout mon problème? (et ce n'est même pas techniquement correct je ne pense pas) – fearofawhackplanet

+2

-1: Désolé, mais la valeur par défaut pour chaque enum est 0, même si 0 est une valeur non valide pour l'énumération. Essayez 'enum MyEnum {M1 = -1, M2 = 1}; MyEnum e = default (MyEnum); ... Console.WriteLine ("{0}", e); 'Ecrit' 0' –

-1

Avez-vous pensé à en faire une méthode générique?

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

L'appelant de la méthode doit connaître le type.

+3

Le 'où T: enum' n'existe pas en C#. :-(C'est tout le problème ici –

+0

Ah vrai, enlevé cela –

+0

Cela fonctionnerait quand même, sans le 'où' .Vous auriez juste besoin d'essayer/attraper pour vous assurer que votre distribution ne se déclenchera pas. lancer une nouvelle exception à l'appelant si T n'était pas une énumération –

5

Je ne suis pas vraiment sûr de ce que vous essayez de faire ici, mais une version de la ligne « par défaut » qui ne compile est ceci:

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

Ou, encore plus propre (de patte, dans les commentaires, merci):

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

Cette deuxième version ne fonctionne correctement que si vous savez premier élément de l'ENUM a une valeur de zéro.

+0

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

+0

@paw Que faire si vous ' re en utilisant ceci: 'enum Foo {a = 1, b = 2}'? +1 à Will cependant, il semble assez robuste –

+0

@Paw: Non 0 n'est pas une valeur définie pour tous les enums –

2

Vous pouvez réellement faire ce Paw is suggesting, même avec une contrainte générique, si vous pouvez déplacer cette méthode pour sa propre classe:

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

Ensuite, vous faire, par exemple:

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 

Comme Konrad Rudolph le signale dans un commentaire, default(TEnum) dans le code ci-dessus évaluera à 0, indépendamment du fait qu'une valeur soit définie ou non pour 0 pour le type donné TEnum. Si ce n'est pas ce que vous voulez, Will's answer fournit certainement la manière la plus simple d'obtenir la première valeur définie ((TEnum)Enum.GetValues(typeof(TEnum)).GetValue(0)).

D'autre part, si vous voulez prendre cela à la extrême, et mettre en cache le résultat de sorte que vous n'avez pas toujours à la boîte, vous pouvez le faire:

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

Votre code ne compile pas pour moi (Mono C#). –

+0

@Konrad: Cela * peut * être parce que j'avais une faute de frappe («TEnumvalue» - pas d'espace). Aussi, je n'ai pas inclus une valeur de retour. Je serais curieux de savoir si cela compile pour Mono maintenant que j'ai mis à jour l'exemple. –

+0

J'avais déjà corrigé cela, n'a pas aidé. Bizarrement, il compile maintenant (+1, hack élégant!) - mais il a le même problème que les autres solutions, à savoir que 'default' renvoie vraiment' 0' qui peut être une valeur indéfinie dans l'énumération réelle et n'est donc pas le bon résultat. Il y a le problème supplémentaire que votre solution ne fonctionne plus comme une méthode d'extension. –

Questions connexes