5

If I have an enum of char's

public enum Action
{
    None,
    Address = 'A',
    Amendment = 'C',
    Normal = 'N'
}

What is the best way to parse a single character string to match the corresponding enum char and match None if not found. TryParse matches the Name and not the value.

For instance if the string I had were "C" I would want to get Action.Amendement

Thanks in advance

1
  • 2
    "I have an enum of char's" - no you don't :) You have an enum of ints, whose values are specified using character literals. Commented Mar 7, 2012 at 8:53

5 Answers 5

5
char c = 'C'; // existent value
var action = Enum.GetValues(typeof(Action)).Cast<Action>().FirstOrDefault(a => (char)a == c);
// action = Action.Amendment

and:

char c = 'X'; // non existent value
var action = Enum.GetValues(typeof(Action)).Cast<Action>().FirstOrDefault(a => (char)a == c);
// action = Action.None
Sign up to request clarification or add additional context in comments.

Comments

4

Just cast it :

Action f = (Action)'C';

If you had a string and were positive it was at least 1 character you can do:

Action f = (Action)"C"[0];

5 Comments

I think that he wants to get Action.None with 'X' for example because 'X' is not a valid value for the enum.
@DarinDimitrov Yeah I noticed that. That's why I upped your answer
This is cleaner thou, and and "we don't need LINQ" to parse an enum, we've been parsing enums since 2003!" omg, ffs.
@b0rg But having a one-liner that can handle incorrect values that return None is not possible without linq I think(hehe rhyme)
@OskarKjellin one liner with 3 extension method calls, one typeof, 1 typecast and a lambda. This is my problem with the linq - it hides the actual purpose of the code, not to mention the awful il its gonna generate. And the usual guessing game "which chained method does not support maybe monad correctly".
3

I'd personally leave them as integers and use DescriptionAttributes and a utility class to get the description attribue for the type. Then you could use more than just a character to display what you wanted.

An example of this is;

    /// <summary>
    /// Returns the string value defined by the description attribute of the given enum.
    /// If no description attribute is available, then it returns the string representation of the enum.
    /// </summary>
    /// <param name="value">Enum to use</param>
    /// <returns>String representation of enum using Description attribute where possible</returns>
    public static string StringValueOf(Enum value)
    {
        FieldInfo fi = value.GetType().GetField(value.ToString());
        DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
        if (attributes.Length > 0)
        {
            return attributes[0].Description;
        }
        else
        {
            return value.ToString();
        }
    }

where your enum is defined as something like;

public enum Action
{
    None,
    [DescriptionAttribute("A")]
    Address,
    [DescriptionAttribute("C")]
    Amendment,
    [DescriptionAttribute("N")]
    Normal
}

2 Comments

thanks, I didn't know about DescriptionAttributes. This helped me (with a different problem but still...)
@DanielGruszczyk - No probs. You aren't limited to DescriptionAttributes either. Any CustomAttribute can be used to do this. We use it for performing mapping of one systems values to another (ie. Enum value represents the value for one system, and we have several description attributes for mapping to other systems, or a better description, or a some other related information that needs coupling with the enum value).
0

Enums are numeric types behind the scenes. You could try a class of public strings:

public class Action()
{
    public const string A = "Address";
    public const string C = "Amendment";
}

If you want to do it 2 ways then you probably want to use a 2 way dictionary collection.

Comments

0

Based on @Mr Moose I want to provide my 2 cents of code. It contains the same method but also includes the reverse method. So in a serialization deserialization case it can be combined.

Include in your code a EnumExtensions class:

using System.ComponentModel;
using System.Linq;
using System.Reflection;

public static class EnumExtensions
{
    /// <summary>
    /// Converts the bare enum value to a string using the <see cref="DescriptionAttribute"/>
    /// that was appplied to it.
    /// </summary>
    /// <typeparam name="TEn"></typeparam>
    /// <param name="enumValue"></param>
    /// <returns></returns>
    public static string ToDescription<TEn>(this TEn enumValue) where TEn : struct
    {
        FieldInfo fi = enumValue.GetType().GetField(enumValue.ToString());

        DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);

        return attributes.Length > 0 ? attributes[0].Description : enumValue.ToString();
    }

    /// <summary>
    /// Does the reverse lookup. If there is an enum member with the string <paramref name="enumString"/>
    /// as <see cref="DescriptionAttribute"/> it will be returned, otherwise the fallback value in
    /// <paramref name="fallback"/> will be returned.
    /// </summary>
    /// <typeparam name="TEn">Type of the enum in question.</typeparam>
    /// <param name="enumString">String serialization of Description annotated enum.</param>
    /// <param name="fallback">Default value to return.</param>
    /// <returns>Either the found value or the fallback.</returns>
    public static TEn FromDescription<TEn>(this string enumString, TEn fallback = default(TEn)) where TEn : struct
    {
        if (enumString != null)
        {
            FieldInfo[] fieldInfo = typeof(TEn).GetFields();

            foreach (var fi in fieldInfo)
            {
                DescriptionAttribute[] attributes =
                    (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
                if (attributes.Any(att => att.Description == enumString))
                {
                    object rawConstantValue = fi.GetRawConstantValue();
                    return (TEn)rawConstantValue;
                }
            }
        }

        return fallback;
    }
}

And supply Enums with the DescriptionAttribute as seen already:

public enum ComparisonOperators
{
    [Description("=")]
    Equal,

    [Description("<>")]
    Unequal,

    [Description("<")]
    LessThan,

    [Description("<=")]
    LessThanOrEqual,

    [Description(">")]
    GreaterThan,

    [Description(">=")]
    GreaterThanOrEqual
}

use it like so:

string v = "<>";
ComparisonOperators x = v.FromDescription(ComparisonOperators.Equal);
string w = x.ToDescription();
Debug.Assert(v==w);  //ok

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.