1

To try make it short, I have created the following enum

public enum Frequency
{
    [Description("Monthly")]
    Monthly,
    [Description("Quarterly")]
    Quarterly,
    [Description("N/A")]
    NA
}

I then have a combo box using the same description strings.

When I select a new selection, specifically the "N/A" one, it fails to read it correctly.

The code that I am using to search for the right enum based on the passed in string is...

/// Returns an enum of the specified type that matches the string value passed in. Note this does ignore case
<param name="value">The string value.</param>        
public static TEnum GetEnum<TEnum>(string value)
{
    if (string.IsNullOrEmpty(value))
    {
        // Default not set value name
        value = "None";
    }
     return (TEnum)System.Enum.Parse(typeof(TEnum), value.Replace(" ", string.Empty), true);
}

So when the value = "N/A", I get the following error..

"An unhandled exception of type 'System.ArgumentException' occurred in mscorlib.dll"

Additional information: Requested value 'N/A' was not found."

I can't seem to understand why this could be happening. There is another, pre-existing combo box where the decription also contains a '/' character and the same error happens. So its not something I have done wrong, it seems, but just the behavior of the enum string checking.

Any insight into why this is causing problems would be incredibly appreciated. :) Thanks!

EDIT: More information..

So this is the code that triggers the enum search..

if (this.FrequencyCombo.SelectedItem != null && !this.FrequencyCombo.SelectedItem.Equals(Utilities.GetDescription(currentLoan.Frequency)))
        {
            currentLoan.Frequency = Utilities.GetEnum<Frequency>(this.FrequencyCombo.SelectedItem.ToString());
        }
Simon
  • 2,065
  • 3
  • 21
  • 28
  • 2
    It's checking against the name (NA), not the description (N/A). – juharr Nov 24 '14 at 15:33
  • there is nothing in the code shown to indicate the Descriptions are used at all. – Ňɏssa Pøngjǣrdenlarp Nov 24 '14 at 15:35
  • Why are you not having the text use the `Description` but the value of your combo be the enum value. – Jamiec Nov 24 '14 at 15:43
  • Thanks for the comments so far! I have added an additional piece of code with does the 'GetEnum' check. Maybe that helps. While I am in the debugger, and I get to the line return (TEnum)System.Enum.Parse(typeof(TEnum), value.Replace(" ", string.Empty), true); When I hover over the 'value' variable it definitely shows as "N/A". So you're saying that it is rather expecting "NA" to be passed, and not "N/A"? – Simon Nov 24 '14 at 15:44

3 Answers3

3

Replace your method with the following, you are trying to match the description with the value:

    /// <summary>
    /// Gets the Enum from a matching description value
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="description"></param>
    /// <returns></returns>
    public static T GetValueFromDescription<T>(string description)
    {
        var type = typeof(T);
        if (!type.IsEnum) throw new InvalidOperationException();
        foreach (var field in type.GetFields())
        {
            var attribute = Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) as DescriptionAttribute;
            if (attribute != null)
            {
                if (attribute.Description == description)
                { 
                    return (T)field.GetValue(null);
                }
            }
            else
            {
                if (field.Name == description)
                { 
                    return (T)field.GetValue(null);
                }
            }
        }

        throw new ArgumentException("Enum description not found.", "Description");            
    }
Mido
  • 452
  • 1
  • 4
  • 13
0

Enum.Parse takes a string argument representing the name of the enum value, not the description, i.e. what Enum.ToString() returns. You'd need a method that finds an enum value by description, like this one:

public static TEnum GetEnumByDescription<TEnum>(string desc) where TEnum : struct
{
    if(string.IsNullOrEmpty(desc))
    {
        return default(TEnum);
    }
    foreach(var field in typeof(TEnum).GetFields(BindingFlags.Static | BindingFlags.Public))
    {
        var attr = (DescriptionAttribute)field.GetCustomAttribute(typeof(DescriptionAttribute));
        if(attr != null && attr.Description == desc)
        {
            return (TEnum)field.GetValue(null);
        }
    }
    return default(TEnum);
}
IS4
  • 11,945
  • 2
  • 47
  • 86
0

Something like this will do. It lists all members, gets their descriptions and compares them to the string you're looking for.

    public static T GetByDescription<T>(string description) {
        return Enum.GetValues(typeof(T))
            .OfType<T>()
            .First(f => {
                var memberInfo = typeof(T).GetMember(f.ToString());
                var desc = memberInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false);
                return desc.Length == 1 && ((DescriptionAttribute)desc[0]).Description.Equals(description, StringComparison.InvariantCultureIgnoreCase);
            });
    }

How to use it:

GetByDescription<Frequency>("Monthly");
GetByDescription<Frequency>("N/A");

Related: Getting attributes of Enum's value

Community
  • 1
  • 1
dusky
  • 1,133
  • 7
  • 12