C#中Enum.Parse的通用版本

Adr*_*der 45 c# generics enums

我经常想知道为什么C#还没有实现Generic Enum.Parse

可以说我有

enum MyEnum
{
   Value1,
   Value2
}
Run Code Online (Sandbox Code Playgroud)

从XML文件/数据库条目我想创建一个枚举.

MyEnum val = (MyEnum)Enum.Parse(typeof(MyEnum), "value1", true);
Run Code Online (Sandbox Code Playgroud)

难道它没有被实现为类似的东西

MyEnum cal = Enum.Parse<MyEnum>("value1");
Run Code Online (Sandbox Code Playgroud)

这似乎是一个小问题,但它似乎是一个被忽视的问题.

有什么想法吗?

Tom*_*ana 40

它已经在.NET 4中实现;)看看这里.

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

此处的讨论还包含一些有趣的观点.

  • 太糟糕了,TryParse <T>和非泛型Parse一样不方便. (32认同)
  • 该链接是非通用的`Enum.Parse`方法.你的意思是链接到新的'Enum.TryParse <T>`方法吗?http://msdn.microsoft.com/en-us/library/system.enum.tryparse%28VS.100%29.aspx (6认同)
  • 有趣的是,他们将其约束为struct,new()而不是向语言添加新的枚举约束. (3认同)
  • 有趣的是,他们甚至不需要对语言设置新的约束 - 它只是一种实际上无法用C#表达的方法.C#编译器可以*服从*约束,即使你不能在C#中编写它们:) (3认同)
  • 注意:使用`Enum.TryParse&lt;T&gt;`,如果你转换一个整数的字符串表示,即`"2"`,它总是成功,无论任何目标枚举成员的int值为`2` . 您必须随后对结果调用 [`IsDefined`](https://msdn.microsoft.com/en-us/library/system.enum.isdefined(v=vs.100).aspx) 以进行完整验证. (3认同)

Ian*_*oyd 16

并在问题的所需语法中:

MyEnum cal = Toolkit.Parse<MyEnum>("value1");
Run Code Online (Sandbox Code Playgroud)

注意:由于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);
}
Run Code Online (Sandbox Code Playgroud)


Mar*_*ski 8

Parse<TEnum>(String)的通用版本 是在 .NET Core 2.0 中引入的。所以你可以这样写

using System;

var e = Enum.Parse<MyEnum>("Value1");
Console.WriteLine($"Enum values is: {e}");

enum MyEnum
{
    Value1,
    Value2
}
Run Code Online (Sandbox Code Playgroud)

请记住,这不在“旧”.Net Framework(.NET 4.8 及更低版本)或任何 .NET 标准中。您需要定位 .NET Core >= 2(或 .NET >= 5,因为 Microsoft放弃了“Core”命名)。

自 .NET Framework 4.0 起,还有TryParse<TEnum>(String, TEnum)的通用版本。所以你可以这样使用它:

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

或者创建您自己的辅助方法,例如:

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");
Run Code Online (Sandbox Code Playgroud)

当然,您可以只使用非通用版本,直到您将项目迁移到较新的 .NET ;)

var e4 = (MyEnum)Enum.Parse(typeof(MyEnum), "Value1");
Run Code Online (Sandbox Code Playgroud)


kvb*_*kvb 6

尽管System.EnumC#不允许约束,但在.NET中允许使用,而C#可以使用具有此类约束的类型或方法.请参阅Jon Skeet的Unconstrained Melody库,其中包含完全符合您要求的代码.

  • Humbug,如果没有人先去那里,我甚至无法插入我自己的图书馆;) (19认同)