Reputation: 3006
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
Upvotes: 5
Views: 3251
Reputation: 789
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
Upvotes: 0
Reputation: 6344
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
}
Upvotes: 3
Reputation: 7141
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.
Upvotes: 0
Reputation: 1038800
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
Upvotes: 5
Reputation: 21880
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];
Upvotes: 4