Разбор строки для совпадения со значением перечисления - PullRequest
5 голосов
/ 07 марта 2012

Если у меня есть перечисление char

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

Каков наилучший способ разбора строки из одного символа на соответствие соответствующему перечислению char и совпадению None, если не найдено. TryParse соответствует имени, а не значению.

Например, если бы у меня была строка "C", я бы хотел получить Action.Amendement

Заранее спасибо

Ответы [ 5 ]

5 голосов
/ 07 марта 2012
char c = 'C'; // existent value
var action = Enum.GetValues(typeof(Action)).Cast<Action>().FirstOrDefault(a => (char)a == c);
// action = Action.Amendment

и

char c = 'X'; // non existent value
var action = Enum.GetValues(typeof(Action)).Cast<Action>().FirstOrDefault(a => (char)a == c);
// action = Action.None
4 голосов
/ 07 марта 2012

Просто разыграйте:

Action f = (Action)'C';

Если у вас была строка, и вы были уверены, что это был как минимум 1 символ, который вы можете сделать:

Action f = (Action)"C"[0];
3 голосов
/ 07 марта 2012

Я бы лично оставил их как целые числа и использовал бы DescriptionAttributes и служебный класс для получения описания атрибута для типа.Тогда вы можете использовать больше, чем просто символ, чтобы отобразить то, что вы хотели.

Примером этого является:

    /// <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();
        }
    }

, где ваше перечисление определяется как что-то вроде:

public enum Action
{
    None,
    [DescriptionAttribute("A")]
    Address,
    [DescriptionAttribute("C")]
    Amendment,
    [DescriptionAttribute("N")]
    Normal
}
0 голосов
/ 26 марта 2019

Исходя из @Mr Moose, я хочу предоставить мои 2 цента кода. Он содержит тот же метод, но также включает и обратный метод. Так что в случае десериализации сериализации это можно объединить.

Включите в свой код класс EnumExtensions:

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

И снабжаем Enums DescriptionAttribute, как уже видели:

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

    [Description("<>")]
    Unequal,

    [Description("<")]
    LessThan,

    [Description("<=")]
    LessThanOrEqual,

    [Description(">")]
    GreaterThan,

    [Description(">=")]
    GreaterThanOrEqual
}

используйте это так:

string v = "<>";
ComparisonOperators x = v.FromDescription(ComparisonOperators.Equal);
string w = x.ToDescription();
Debug.Assert(v==w);  //ok
0 голосов
/ 07 марта 2012

Перечисления - это числовые типы за сценой. Вы можете попробовать класс открытых строк:

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

Если вы хотите сделать это 2-мя способами, то вы, вероятно, захотите использовать двухстороннюю коллекцию словарей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...