I have regularly wondered why C# has not yet implemeted a Generic Enum.Parse
Lets say I have
enum MyEnum
{
Value1,
Value2
}
And from an XML file/DB entry I wish to to create an Enum.
MyEnum val = (MyEnum)Enum.Parse(typeof(MyEnum), "value1", true);
Could it not have been implemented as something like
MyEnum cal = Enum.Parse<MyEnum>("value1");
This 开发者_运维百科might seem like a small issue, but it seems like an overlooked one.
Any thoughts?
It is already implemented in .NET 4 ;) Take a look here.
MyEnum cal;
if (!Enum.TryParse<MyEnum>("value1", out cal))
throw new Exception("value1 is not valid member of enumeration MyEnum");
Also the discussion here contains some interesting points.
And in the desired syntax of the question:
MyEnum cal = Toolkit.Parse<MyEnum>("value1");
Note: Since C# forbids you from adding static extensions, you have to house the function elsewhere. i use a static Toolkit
class that contains all these useful bits:
/// <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);
}
Although constraining to System.Enum
isn't allowed by C#, it is allowed in .NET and C# can use types or methods with such constraints. See Jon Skeet's Unconstrained Melody library, which includes code that does exactly what you want.
The generic version of Parse<TEnum>(String) was introduced in .NET Core 2.0. So you can just write:
class Program
{
static void Main(string[] args)
{
var e = Enum.Parse<MyEnum>("Value1");
Console.WriteLine($"Enum values is: {e}");
}
}
enum MyEnum
{
Value1,
Value2
}
Just keep in mind this is not in "old" .Net Framework (.NET 4.8 and less) or in any .NET Standard. You need to target .NET Core >= 2 (or .NET >= 5 since Microsoft dropped "Core" naming).
There is generic version of TryParse<TEnum>(String, TEnum) since .NET Framework 4.0. So you can use it like that:
if (Enum.TryParse<MyEnum>("Value2", out var e2))
{
Console.WriteLine($"Enum values is: {e2}");
}
or create your own helper method like:
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");
and of course you can just use non-generic version until you migrate your project to newer .NET ;)
var e4 = (MyEnum)Enum.Parse(typeof(MyEnum), "Value1");
public class EnumHelper
{
public static T? TryParse<T>(string text)
where T: struct
{
if (string.IsNullOrEmpty(text))
{
return null;
}
T r;
if (Enum.TryParse<T>(text, out r))
{
return r;
}
return null;
}
}
Slightly modified version of @ian-boyd's answer, using an extension method to avoid the need to specify a static class name in the call:
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);
}
While tweaking a little with some methods, trying to build something similar to the initial proposal:
MyEnum cal = Enum.Parse<MyEnum>("value1");
it seemed to me that this syntax won´t be possible in C#, since the Enum type is treated as non-nullable.
If we call the "Enum.TryParse" method passing a value not corresponding to an item of the enum, the Enum´s default value will be returned in the "out" variable. That´s why we need to test the "Enum.TryParse" result first, since simply calling
MyEnum cal;
Enum.TryParse<MyEnum>("value1", out cal);
and checking "cal" value will not always give a reliable result.
精彩评论