tags:

views:

53

answers:

2

Hi

Suppose enum:

public enum SysLogsAppTypes { None, MonitorService, MonitorTool };

and here is a function to convert from the ToString() representation back to enum:

private SysLogsAppTypes Str2SysLogsAppTypes(string str)  
{  
    try  
    {  
        SysLogsAppTypes res = (SysLogsAppTypes)Enum
                                       .Parse(typeof(SysLogsAppTypes), str);  
        if (!Enum.IsDefined(typeof(SysLogsAppTypes), res)) 
            return SysLogsAppTypes.None;  
        return res;  
    }  
    catch  
    {  
    return SysLogsAppTypes.None;  
    }  
}  

Is there a way to make this Generic ??

I tried:

private T Str2enum<T>(string str)   
{  
    try  
    {  
        T res = (T)Enum.Parse(typeof(T), str);  
        if (!Enum.IsDefined(typeof(T), res)) return T.None;  
        return res;  
    }  
    catch  
    {  
        return T.None;  
    }  
}  

but I get: 'T' is a 'type parameter', which is not valid in the given context
where there is T.None

Any help ? Thanks
Micha

+3  A: 

I think the default keyword is what you need:

private T Str2enum<T>(string str) where T : struct
{   
    try   
    {   
        T res = (T)Enum.Parse(typeof(T), str);   
        if (!Enum.IsDefined(typeof(T), res)) return default(T);   
        return res;   
    }   
    catch   
    {   
        return default(T);   
    }   
}   
jball
This is the correct answer, but it's important to note that the "default" enum is whatever value is represented by 0. This is usually the first value. However, if your enum starts at 1, you will return `0` instead of any legal value in the enum. Using this method would require a caveat for this behavior or some coding standard. For instance, I've seen some enums where a `NONE` value is the last value, which would not work in this method.
Jim Schubert
+2  A: 

Not the way you are trying it, but I use the method below to do this:

 public static bool EnumTryParse<E>(string enumVal, out E resOut) 
        where E : struct
 {
      var enumValFxd = enumVal.Replace(' ', '_');
      if (Enum.IsDefined(typeof(E), enumValFxd))
      {
          resOut = (E)Enum.Parse(typeof(E), 
             enumValFxd, true);
          return true;
      }
      // ----------------------------------------
      foreach (var value in
          Enum.GetNames(typeof (E)).Where(value => 
              value.Equals(enumValFxd, 
              StringComparison.OrdinalIgnoreCase)))
      {
          resOut = (E)Enum.Parse(typeof(E), value);
          return true;
      }
      resOut = default(E);
      return false;
 }

No exceptions thrown here ...

Charles Bretana
I love this solution. I always prefer a TryParse over the assumption that values are legit.
Jim Schubert
+1 - I like the `TryParse` pattern, but a note: by doing the `Enum.IsDefined` method call before attempting to convert, this will fail to convert string representations of the underlying value of an `enum`. That's one benefit of the `try catch` and then check `Enum.IsDefined` algorithm. I suppose you could do an `int.TryParse` first and add a special case for that to the above solution.
jball
@jball, by " string representations of the underlying value ", are you talking about like, "1", "12", "one" or "two" or "TwentyThree" ??
Charles Bretana
Digits, e.g., "2", "3", "12"
jball