Разобрать строку в тип enum - PullRequest
16 голосов
/ 15 сентября 2009

У меня есть тип перечисления в качестве примера:

public Enum MyEnum {
    enum1, enum2, enum3 };

Я прочитаю строку из файла конфигурации. Что мне нужно, чтобы разобрать строку для типа MyEnum или ноль или не определен. Не уверен, что следующие коды будут работать (извините за то, что у меня нет доступа к моей VS прямо сейчас):

// example: ParseEnum<MyEnum>("ENUM1", ref eVal);
bool ParseEnum<T>(string value1, ref eVal) where T : Enum
{
  bool bRet = false;
  var x = from x in Enum.GetNames(typeof(T)) where 
       string.Equals(value1, x, StringComparison. OrdinalIgnoreCase)
       select x;
  if (x.Count() == 1 )
  {
    eVal = Enum.Parse(typeof(T), x.Item(0)) as T;
    bRet = true;
  }
  return bRet;
}

Не уверен, что это правильно, или есть какой-то другой простой способ разбора строки на значение MyEnum?

Ответы [ 8 ]

31 голосов
/ 15 сентября 2009

Как насчет чего-то вроде:

public static class EnumUtils
{
    public static Nullable<T> Parse<T>(string input) where T : struct
    {
        //since we cant do a generic type constraint
        if (!typeof(T).IsEnum)
        {
            throw new ArgumentException("Generic Type 'T' must be an Enum");
        }
        if (!string.IsNullOrEmpty(input))
        {
            if (Enum.GetNames(typeof(T)).Any(
                  e => e.Trim().ToUpperInvariant() == input.Trim().ToUpperInvariant()))
            {
                return (T)Enum.Parse(typeof(T), input, true);
            }
        }
        return null;
    }
}

Используется как:

MyEnum? value = EnumUtils.Parse<MyEnum>("foo");

(Примечание: используется старая версия try/catch вокруг Enum.Parse)

5 голосов
/ 15 сентября 2009
private enum MyEnum
{
    Enum1 = 1, Enum2 = 2, Enum3 = 3, Enum4 = 4, Enum5 = 5, Enum6 = 6, 
    Enum7 = 7, Enum8 = 8, Enum9 = 9, Enum10 = 10
}

private static Object ParseEnum<T>(string s)
{
    try
    {
        var o = Enum.Parse(typeof (T), s);
        return (T)o;
    }
    catch(ArgumentException)
    {
        return null;
    }
}

static void Main(string[] args)
{
   Console.WriteLine(ParseEnum<MyEnum>("Enum11"));
   Console.WriteLine(ParseEnum<MyEnum>("Enum1"));
   Console.WriteLine(ParseEnum<MyEnum>("Enum6").GetType());
   Console.WriteLine(ParseEnum<MyEnum>("Enum10"));
}

ВЫВОД:

    //This line is empty as Enum11 is not there and function returns a null
Enum1
TestApp.Program+MyEnum
Enum10
Press any key to continue . . .
4 голосов
/ 03 августа 2013

Это старый вопрос, но теперь в .NET 4.5 есть Enum.TryParse ().

http://msdn.microsoft.com/en-us/library/dd991317.aspx

2 голосов
/ 15 сентября 2009

Я только что скомбинировал синтаксис из здесь , с обработкой исключений из здесь , чтобы создать это:

public static class Enum<T>
{
    public static T Parse(string value)
    {
        //Null check
        if(value == null) throw new ArgumentNullException("value");
        //Empty string check
        value = value.Trim();
        if(value.Length == 0) throw new ArgumentException("Must specify valid information for parsing in the string", "value");
        //Not enum check
        Type t = typeof(T);
        if(!t.IsEnum) throw new ArgumentException("Type provided must be an Enum", "TEnum");

        return (T)Enum.Parse(typeof(T), value);
    }
}

Вы можете немного повернуть его, чтобы возвратить ноль вместо выдачи исключений.

2 голосов
/ 15 сентября 2009

У меня есть TryParseName метод в UnconstrainedMelody , библиотека для методов делегатов и вспомогательных перечислений, которая использует «невыразимые» ограничения с помощью некоторых хитростей после сборки. (Код с использованием библиотека не нуждается в пост-сборке, просто для ясности.)

Вы бы использовали это так:

Foo foo;
bool parsed = Enums.TryParseName<Foo>(name, out foo);

В настоящее время у меня нет версии без учета регистра, но я мог бы легко представить ее, если хотите. Обратите внимание, что не пытается проанализировать числа, например «12», как встроенная версия, и не пытается анализировать разделенные запятыми списки флагов. Я могу добавить версию флагов позже, но я не вижу особого смысла в числовой версии.

Это делается без бокса и без проверки типа времени выполнения. Наличие ограничения действительно удобно:)

Пожалуйста, дайте мне знать, если вам будет полезен анализ без учета регистра ...

2 голосов
/ 15 сентября 2009

Если вы используете .NET 3.5 (или даже 2.0, если вы сократили метод расширения), мне очень повезло с методами, описанными в этой статье:

Перечисления и строки - остановите безумие!

РЕДАКТИРОВАТЬ: домен исчез, и теперь это ферма ссылок. Я вытащил код (немного измененный и со временем добавленный) из нашей кодовой базы на работе, которую вы теперь можете найти здесь:

https://gist.github.com/1305566

1 голос
/ 11 сентября 2012

Вы можете использовать TryParse, если хотите избежать использования try / catch.

MyEnum eVal;
if (Enum.TryParse("ENUM2", true, out eVal)){
    // now eVal is the enumeration element: enum2 
}
//unable to parse. You can log the error, exit, redirect, etc...

Я немного изменил выбранный ответ. Надеюсь тебе понравится.

public static class EnumUtils
{
    public static Nullable<T> Parse<T>(string input) where T : struct
    {
        //since we cant do a generic type constraint
        if (!typeof(T).IsEnum)
        {
            throw new ArgumentException("Generic Type 'T' must be an Enum");
        }

        int intVal;
        if (!string.IsNullOrEmpty(input) && !int.TryParse(input, out intVal))
        {
            T eVal;
            if (Enum.TryParse(input, true, out eVal))
            {
                return eVal;
            }
        }
        return null;
    }
}
0 голосов
/ 31 июля 2017

Возвращать Enum по строке, если содержит:

    public static T GetEnum<T>(string s)
    {
        Array arr = Enum.GetValues(typeof(T));
        foreach (var x in arr)
        {
            if (x.ToString().Contains(s))
                return (T)x;
        }
        return default(T);
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...