Подтвердить что ты не робот

Как я могу проверить, определено ли перечисление или нет, игнорируя регистр?

Следующий общий статический метод принимает строку и возвращает перечисление.

Это красиво игнорирует регистр, поскольку я устанавливаю для параметра ignoreCase значение true.

Однако я также хочу проверить, существует ли перечисление, но метод enum.IsDefined для этого не имеет параметра ignoreCase. p >

Как я могу проверить, определено ли перечисление или нет, и в том же случае игнорировать?

using System;

namespace TestEnum2934234
{
    class Program
    {
        static void Main(string[] args)
        {
            LessonStatus lessonStatus = StringHelpers.ConvertStringToEnum<LessonStatus>("prepared");
            ReportStatus reportStatus = StringHelpers.ConvertStringToEnum<ReportStatus>("finished");

            Console.WriteLine(lessonStatus.ToString());
            Console.WriteLine(reportStatus.ToString());
            Console.ReadLine();
        }
    }

    public static class StringHelpers
    {
        public static T ConvertStringToEnum<T>(string text)
        {
            if (Enum.IsDefined(typeof(T), text)) //does not have ignoreCase parameter
                return (T)Enum.Parse(typeof(T), text, true);
            else
                return default(T);
        }
    }

    public enum LessonStatus
    {
        Defined,
        Prepared,
        Practiced,
        Recorded
    }

    public enum ReportStatus
    {
        Draft,
        Revising,
        Finished
    }
}
4b9b3361

Ответ 1

public enum MyEnum
{
    Bar,
    Foo
}

class Program
{
    static void Main(string[] args)
    {
        var containsFoo = Enum.GetNames(typeof(MyEnum)).Any(x => x.ToLower() == "foo");
        Console.WriteLine(containsFoo);
    }
}

Ответ 2

Наряду с ответом @Darin в .NET 4.0 тип Enum теперь имеет метод TryParse:

MyEnum result;
Enum.TryParse("bar", true, out result);

Важно помнить, что существует фундаментальное различие в поведении Parse vs TryParse. Методы анализа порождают исключения. Методы TryParse не будут. Это очень важно знать, если вы потенциально пытаетесь проанализировать многие элементы.

Ответ 3

Я использую Compact Framework 3.5 и:

Enum.TryParse

... не существует. Он имеет:

Enum.IsDefined

.. но это не поддерживает параметр ignoreCase. Я бы хотел получить лучшее из обоих миров, поэтому придумал это (как вспомогательный метод)...

public bool TryParse<TEnum>(string value, bool ignoreCase, ref TEnum result) where TEnum : struct
{
    bool parsed;
    try
    {
        result = (TEnum)Enum.Parse(typeof(TEnum), value, ignoreCase);
        parsed = true;
    }
    catch { }
    return parsed;
}

НТН

Ответ 4

Вместо этого используйте Enum.TryParse:

T val;

if(Enum.TryParse(text, true, out val))
    return val;
else 
    return default(T);

Ответ 5

Вы могли бы уйти просто с помощью Enum.TryParse, как говорили другие.

Однако, если вы хотите более надежное/общее преобразование, которое позволяет вам конвертировать больше, чем просто строки, вам также нужно использовать Enum.IsDefined, который, к сожалению, по вашему усмотрению, не не чувствителен к регистру.

Enum.TryParse является (может быть) нечувствительным к регистру. Но, к сожалению, он позволяет выйти из дальнего зарубежья!

Итак, решение состоит в том, чтобы использовать их вместе (и порядок важен).

Я написал метод расширения, который делает именно это. Он позволяет конвертировать из строки, int/int? И любого другого Enum/Enum? типа типа:

string value1 = "Value1";
Enum2 enum2 = value1.ParseToEnum<Enum2>();
Debug.Assert(enum2.ToString() == value1);

Enum1 enum1 = Enum1.Value1;
enum2 = enum1.ParseToEnum<Enum2>();
Debug.Assert(enum2.ToString() == enum1.ToString());

int value2 = 1;
enum2 = value2.ParseToEnum<Enum2>();
Debug.Assert(enum2.GetHashCode() == value2);

Здесь сердце метода. Это часть преобразования, которая отвечает на ваш вопрос. Переменная value имеет тип object из-за "перегрузок", которые у меня есть, которые принимают разные типы в качестве основного входа (см. Выше), но вы можете сделать это с переменной типа string просто отлично, если все вы хотите (явно меняя value.ToString() на value).

if (value != null)
{
    TEnum result;
    if (Enum.TryParse(value.ToString(), true, out result))
    {
        // since an out-of-range int can be cast to TEnum, double-check that result is valid
        if (Enum.IsDefined(typeof(TEnum), result.ToString()))
        {
            return result;
        }
    }
}

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

Ответ 6

    enum DaysCollection
    {
     sunday,
     Monday,
     Tuesday,
     Wednesday,
     Thursday,
     Friday,
     Saturday
    }

    public bool isDefined(string[] arr,object obj)
    {
        bool result=false;
        foreach (string enu in arr)
        {
              result = string.Compare(enu, obj.ToString(), true) == 0;
              if (result)
                  break;

        }
        return result;


    }

    private void button1_Click(object sender, EventArgs e)
    {
        object obj = "wednesday";
        string[] arr = Enum.GetNames(typeof(DaysCollection)).ToArray();

        isDefined(arr,obj);
    }

Ответ 7

public static T ConvertStringToEnum<T>(string text)
{
    T returnVal;
    try
    {
        returnVal = (T) Enum.Parse( typeof(T), text, true );
    }
    catch( ArgumentException )
    {
        returnVal = default(T);
    }
    return returnVal;
}

Ответ 8

Сделайте текст в том же случае, что и строка перечисления:

enum FileExts
{
  jpg,
  pdf
}

if (Enum.IsDefined(typeof(T), text.tolower())) //does not have ignoreCase parameter
    return (T)Enum.Parse(typeof(T), text, true);
else
    return default(T);

Ответ 9

У меня была аналогичная проблема, и я использовал комбинацию как .Enum.TryPase (с флагом, чувствительным к регистру, как true) и Enum.IsDefined. В качестве упрощения для вашего вспомогательного класса рассмотрите следующее:

public static class StringHelpers
{
    public static T ConvertStringToEnum<T>(string text)
    {
        T result;
        return Enum.TryParse(text, true, out result)
            && Enum.IsDefined(result.ToString())
                ? result
                : default(T);
    }
}

И пока мы на нем, так как класс-помощник статичен, а метод статичен, мы можем сделать это методом расширения на string.

public static class StringExtensions
{
    public static TEnum ToEnum<TEnum>(this string text)
        where TEnum : struct, IComparable, IFormattable, IConvertible 
    {
        TEnum result = default(TEnum);
        return !string.IsNullOrWhiteSpace(text) 
            && Enum.TryParse(text, true, out result)
            && Enum.IsDefined(typeof(TEnum), result.ToString())
                ? result
                : default(TEnum);
    }
}

Здесь я создал .NET Fiddle, который наглядно демонстрирует это.