Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Универсальная версия Enum.Parse в C #

Автор вопроса: Adriaan StanderОтветов: 6

Я регулярно задавался вопросом, почему C # до сих пор не реализовал Generic Enum.Parse

Допустим, у меня есть

enum MyEnum
{
   Value1,
   Value2
}

И из XML-файла / записи в БД я хочу создать Enum.

MyEnum val = (MyEnum)Enum.Parse(typeof(MyEnum), "value1", true);

Разве это не могло быть реализовано как что-то вроде

MyEnum cal = Enum.Parse<MyEnum>("value1");

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

Есть предположения?

genericsenums

Ответы

Ответ 1 · рейтинг 43 · Tomas Vana

Это уже реализовано в .NET 4;) Взгляните на здесь.

MyEnum cal;
if (!Enum.TryParse<MyEnum>("value1", out cal))
   throw new Exception("value1 is not valid member of enumeration MyEnum");

Кроме того, здесь обсуждение также содержит некоторые интересные моменты.

Ответ 2 · рейтинг 18 · Ian Boyd

И в желаемом синтаксисе вопроса:

MyEnum cal = Toolkit.Parse<MyEnum>("value1");

Примечание. Поскольку C # запрещает добавлять статические расширения, вам необходимо разместить функцию в другом месте. Я использую статический класс Toolkit, который содержит все эти полезные биты:

/// <summary>
/// Converts the string representation of the name or numeric value of one or
//  more enumerated constants to an equivalent enumerated object.
/// </summary>
/// <typeparam name="TEnum">An enumeration type.</typeparam>
/// <param name="value">A string containing the name or value to convert.</param>
/// <returns>An object of type TEnum whose value is represented by value</returns>
/// <exception cref="System.ArgumentNullException">enumType or value is null.</exception>
/// <exception cref=" System.ArgumentException"> enumType is not an System.Enum. -or-
/// value is either an empty string or only contains white space.-or-
/// value is a name, but not one of the named constants defined for the enumeration.</exception>
/// <exception cref="System.OverflowException">value is outside the range of the underlying type of enumType.</exception>
public static TEnum Parse<TEnum>(String value) where TEnum : struct
{
   return (TEnum)Enum.Parse(typeof(TEnum), value);
}

Ответ 3 · рейтинг 8 · kvb

Хотя ограничение System.Enum не разрешено в C #, оно разрешено в .NET, и C # может использовать типы или методы с такими ограничениями. См. Библиотеку Джона Скита Unconstrained Melody, которая включает код, который делает именно то, что вы хотите.

Ответ 4 · рейтинг 2 · Jimmy

Слегка измененная версия ответа @ ian-boyd с использованием метода расширения, чтобы избежать необходимости указывать имя статического класса в вызове:

MyEnum cal = "value1".Parse<MyEnum>();

/// <summary>
/// Converts the string representation of the name or numeric value of one or
//  more enumerated constants to an equivalent enumerated object.
/// </summary>
/// <typeparam name="TEnum">An enumeration type.</typeparam>
/// <returns>An object of type TEnum whose value is represented by value</returns>
/// <exception cref="System.ArgumentNullException">enumType or value is null.</exception>
/// <exception cref=" System.ArgumentException"> enumType is not an System.Enum. -or-
/// value is either an empty string or only contains white space.-or-
/// value is a name, but not one of the named constants defined for the enumeration.</exception>
/// <exception cref="System.OverflowException">value is outside the range of the underlying type of enumType.</exception>
public static TEnum Parse<TEnum>(this String value) where TEnum : struct
{
   return (TEnum)Enum.Parse(typeof(TEnum), value);
}

Ответ 5 · рейтинг 1 · Mariusz Pawelski

Общая версия Parse ‹ TEnum ›(String) был представлен в .NET Core 2.0. Так что вы можете просто написать:

    class Program
    {
        static void Main(string[] args)
        {
            var e = Enum.Parse<MyEnum>("Value1");
            Console.WriteLine($"Enum values is: {e}");
        }
    }

    enum MyEnum
    {
        Value1,
        Value2
    }

Просто имейте в виду, что этого нет в старой .Net Framework (.NET 4.8 и ниже) или в каком-либо стандарте .NET. Вам необходимо настроить таргетинг на .NET Core ›= 2 (или .NET› = 5, поскольку Microsoft упал Core naming).

Имеется общая версия class Program { static void Main(string[] args) { var e = Enum.Parse<MyEnum>("Value1"); Console.WriteLine($"Enum values is: {e}"); } } enum MyEnum { Value1, Value2 } System_String___0__" rel="nofollow noreferserer">TryParserer ‹TEnum› (String, TEnum), начиная с .NET Framework 4.0. Таким образом, вы можете использовать это так:

if (Enum.TryParse<MyEnum>("Value2", out var e2))
{
    Console.WriteLine($"Enum values is: {e2}");
}

или создайте свой собственный вспомогательный метод, например:

public static class EnumUtils
{
    public static TEnum Parse<TEnum>(String value) where TEnum : struct
    {
        return (TEnum)Enum.Parse(typeof(TEnum), value);
    }
}

...
var e3 = EnumUtils.Parse<MyEnum>("Value1");

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

var e4 = (MyEnum)Enum.Parse(typeof(MyEnum), "Value1");

Ответ 6 · Jose Tepedino

Немного подправив некоторые методы, пытаясь построить что-то похожее на первоначальное предложение:

MyEnum cal = Enum.Parse<MyEnum>("value1");

Мне казалось, что такой синтаксис невозможен в C #, поскольку тип Enum рассматривается как не допускающий значения NULL.

Если мы вызываем метод "Enum.TryParse", передавая значение, не соответствующее элементу перечисления, значение Enum по умолчанию будет возвращено в переменной "out". Вот почему нам нужно сначала протестировать результат "Enum.TryParse", поскольку простой вызов

MyEnum cal;
Enum.TryParse<MyEnum>("value1", out cal);

и проверка значения "cal" не всегда дает надежный результат.

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы