在 C 中将字符串转换为枚举#

Convert a string to an enum in C#

提问人:Ben Mills 提问时间:8/19/2008 最后编辑:David KlempfnerBen Mills 更新时间:1/11/2023 访问量:1182113

问:

在 C# 中将字符串转换为枚举值的最佳方法是什么?

我有一个包含枚举值的 HTML select 标签。当页面发布时,我想获取值(将采用字符串的形式)并将其转换为相应的枚举值。

在一个理想的世界里,我可以做这样的事情:

StatusEnum MyStatus = StatusEnum.Parse("Active");

但这不是有效的代码。

C# 字符串 枚举

评论


答:

132赞 DavidWhitney 8/19/2008 #1

您正在寻找 Enum.Parse

SomeEnum enum = (SomeEnum)Enum.Parse(typeof(SomeEnum), "EnumValue");

评论

4赞 Allen Wahlberg 7/31/2022
使用 value 代替 enum;SomeEnum 值 = (SomeEnum)Enum.Parse(typeof(SomeEnum), “EnumValue”);
2098赞 Keith 8/19/2008 #2

在 .NET Core 和 .NET Framework ≥4.0 中,有一个通用的分析方法

Enum.TryParse("Active", out StatusEnum myStatus);

这还包括 C#7 的新内联变量,因此这会执行 try-parse、转换为显式枚举类型并初始化 + 填充变量。outmyStatus

如果您可以访问 C#7 和最新的 .NET,这是最好的方法。

原始答案

在 .NET 中,它相当丑陋(直到 4 或更高版本):

StatusEnum MyStatus = (StatusEnum) Enum.Parse(typeof(StatusEnum), "Active", true);

我倾向于用以下方法简化这一点:

public static T ParseEnum<T>(string value)
{
    return (T) Enum.Parse(typeof(T), value, true);
}

然后我可以做:

StatusEnum MyStatus = EnumUtil.ParseEnum<StatusEnum>("Active");

评论中建议的一个选项是添加一个扩展,这很简单:

public static T ToEnum<T>(this string value)
{
    return (T) Enum.Parse(typeof(T), value, true);
}

StatusEnum MyStatus = "Active".ToEnum<StatusEnum>();

最后,如果无法解析字符串,您可能希望使用默认枚举:

public static T ToEnum<T>(this string value, T defaultValue) 
{
    if (string.IsNullOrEmpty(value))
    {
        return defaultValue;
    }

    T result;
    return Enum.TryParse<T>(value, true, out result) ? result : defaultValue;
}

这使得它成为:

StatusEnum MyStatus = "Active".ToEnum(StatusEnum.None);

但是,我会小心地将这样的扩展方法添加到(没有命名空间控制)中,无论它们是否持有枚举,它都会出现在所有实例上(因此是有效的,但毫无意义)。通常最好避免使用仅适用于非常特定上下文的额外方法混淆 Microsoft 的核心类,除非您的整个开发团队非常了解这些扩展的功能。stringstring1234.ToString().ToEnum(StatusEnum.None)

评论

25赞 Nash 7/20/2009
如果性能很重要(始终如此),Mckenzieg1 在下面给出的 chk 答案:stackoverflow.com/questions/16100/...
36赞 Keith 7/20/2009
@avinashr@McKenzieG1的回答是正确的,但这并不总是重要的。例如,如果您要为每次解析进行数据库调用,那么担心枚举解析将毫无意义。
7赞 Keith 8/22/2013
@H.M. 我不认为扩展在这里是合适的 - 这是一个特例,扩展将适用于每个字符串。如果你真的想这样做,那将是一个微不足道的改变。
10赞 Elaine 6/3/2014
Enum.TryParse怎么样?
21赞 bbrik 12/23/2015
很好。在上一个示例中,您需要一个 where T : 结构。
19赞 tags2k 8/19/2008 #3

Enum.Parse 是你的朋友:

StatusEnum MyStatus = (StatusEnum)Enum.Parse(typeof(StatusEnum), "Active");
24赞 brendan 8/19/2008 #4
object Enum.Parse(System.Type enumType, string value, bool ignoreCase);

因此,如果你有一个名为 mood 的枚举,它将如下所示:

   enum Mood
   {
      Angry,
      Happy,
      Sad
   } 

   // ...
   Mood m = (Mood) Enum.Parse(typeof(Mood), "Happy", true);
   Console.WriteLine("My mood is: {0}", m.ToString());
8赞 Mark Cidade 8/19/2008 #5
// str.ToEnum<EnumType>()
T static ToEnum<T>(this string str) 
{ 
    return (T) Enum.Parse(typeof(T), str);
}
241赞 McKenzieG1 9/2/2008 #6

请注意,性能并不理想,因为它是通过反射实现的。(反之亦然。Enum.Parse()Enum.ToString()

如果您需要在性能敏感的代码中将字符串转换为枚举,最好的办法是在启动时创建一个,并使用它来进行转换。Dictionary<String,YourEnum>

评论

30赞 John Stock 12/14/2017
哇,3ms是可怕的几个数量级
3赞 Transformer 1/5/2018
您能否围绕此添加一个代码示例,以便我们了解如何替换和使用
3赞 Lionet Chen 10/19/2020
虽然 3 毫秒的第一次运行肯定很糟糕,但第二次运行会更好吗?如果每次都是 3 毫秒,那么我们会像瘟疫一样避免它
3赞 Fanblade 11/18/2022
Enum.Parse 需要纳秒,而不是毫秒,至少使用现代 .NET 版本是这样。我在 .NET 6 中使用 BenchmarkDotNet 测试了此代码: 它产生了以下结果: 平均值:33.19 ns 错误:0.469 ns 标准开发:0.392 nsMyEnum myEnum = Enum.Parse<MyEnum>("Seven");
3赞 Fanblade 11/19/2022
.NET Framework 的速度几乎与 .NET 6 一样快,在所有 .NET Framework 版本 4.6.1-4.8.1 上以 175 ns 的速度运行以下代码: .这并不“可怕”。Enum.TryParse<MyEnum>(Input, out MyEnum result);
13赞 gap 8/30/2012 #7

我们不能假设输入完全有效,于是采用了@Keith答案的变体:

public static TEnum ParseEnum<TEnum>(string value) where TEnum : struct
{
    TEnum tmp; 
    if (!Enum.TryParse<TEnum>(value, true, out tmp))
    {
        tmp = new TEnum();
    }
    return tmp;
}
7赞 jite.gs 10/18/2013 #8

将字符串解析为 TEnum,而无需 try/catch 和 .NET 4.5 中的 TryParse() 方法

/// <summary>
/// Parses string to TEnum without try/catch and .NET 4.5 TryParse()
/// </summary>
public static bool TryParseToEnum<TEnum>(string probablyEnumAsString_, out TEnum enumValue_) where TEnum : struct
{
    enumValue_ = (TEnum)Enum.GetValues(typeof(TEnum)).GetValue(0);
    if(!Enum.IsDefined(typeof(TEnum), probablyEnumAsString_))
        return false;

    enumValue_ = (TEnum) Enum.Parse(typeof(TEnum), probablyEnumAsString_);
    return true;
}

评论

1赞 jite.gs 10/30/2013
如果代码已经包含描述,是否需要进行描述?好的,我做了这个:)
402赞 Erwin Mayer 12/5/2013 #9

使用 Enum.TryParse<T>(String, T) (≥ .NET 4.0):

StatusEnum myStatus;
Enum.TryParse("Active", out myStatus);

使用 C# 7.0 的参数类型内联可以进一步简化它:

Enum.TryParse("Active", out StatusEnum myStatus);

评论

54赞 DanM7 3/1/2014
添加中间的布尔参数来区分大小写,这是迄今为止最安全、最优雅的解决方案。
23赞 TEK 3/18/2016
来吧,你们中有多少人实施了 2008 年的选定答案,只是向下滚动并发现这是更好的(现代)答案。
0赞 yair 1/5/2018
我不明白。 抛出转换出错的解释性异常(值为 ,空或没有相应的枚举常量),这比 的布尔返回值(抑制具体错误)要好得多ParsenullTryParse
6赞 Mass Dot Net 9/12/2019
Enum.TryParse<T>(String, T) 在解析整数字符串时存在缺陷。例如,以下代码将成功地将无意义的字符串解析为无意义的枚举:var result = Enum.TryParse<System.DayOfWeek>("55", out var parsedEnum);
4赞 Walter 6/2/2020
@MassDotNet 在这种情况下,添加:以确保解析的枚举确实存在。&& Enum.IsDefined(typeof(System.DayOfWeek), parsedEnum)
43赞 Foyzul Karim 2/10/2014 #10

您现在可以使用扩展方法

public static T ToEnum<T>(this string value, bool ignoreCase = true)
{
    return (T) Enum.Parse(typeof (T), value, ignoreCase);
}

您可以通过以下代码调用它们(这里是枚举类型):FilterType

FilterType filterType = type.ToEnum<FilterType>();

评论

1赞 RealSollyM 2/14/2014
我已经更新了它,将值作为对象并将其转换为此方法中的字符串。这样我就可以取一个 int 值。ToEnum 而不是字符串。
2赞 Svish 12/9/2014
@SollyM我会说这是一个可怕的想法,因为这个扩展方法将适用于所有对象类型。在我看来,两种扩展方法,一种用于字符串,一种用于 int,会更干净、更安全。
0赞 RealSollyM 12/10/2014
@Svish,这是真的。我这样做的唯一原因是因为我们的代码仅在内部使用,我想避免编写 2 个扩展。而且由于我们唯一一次转换为 Enum 是使用 string 或 int,因此我不认为这是问题。
3赞 Svish 12/11/2014
@SollyM内部与否,我仍然是维护和使用我的代码:P如果我在每个智能菜单中都启动了一个 ToEnum,我会很生气,就像你说的,因为你唯一一次转换为枚举是从 string 或 int,你可以很确定你只需要这两个方法。两种方法并不比一种多,尤其是当它们这么小且属于实用型时:P
15赞 Nelly 12/9/2014 #11

您可以使用默认值扩展接受的答案以避免异常:

public static T ParseEnum<T>(string value, T defaultValue) where T : struct
{
    try
    {
        T enumValue;
        if (!Enum.TryParse(value, true, out enumValue))
        {
            return defaultValue;
        }
        return enumValue;
    }
    catch (Exception)
    {
        return defaultValue;
    }
}

然后你这样称呼它:

StatusEnum MyStatus = EnumUtil.ParseEnum("Active", StatusEnum.None);

如果默认值不是枚举,则 Enum.TryParse 将失败并引发捕获的异常。

在许多地方的代码中使用此函数多年后,也许最好添加此操作需要性能的信息!

评论

0赞 Daniël Tulp 5/26/2016
我不喜欢默认值。它可能导致不可预测的结果。
7赞 andleer 5/28/2016
什么时候会抛出异常?
0赞 Nelly 1/7/2020
@andleer枚举值是否适合与默认值相同的枚举类型
0赞 andleer 1/7/2020
@Nelly 此处的旧代码,但 和 方法返回类型均为 类型。如果类型不同,您将收到编译时错误:“无法从'ConsoleApp1.Size'转换为'ConsoleApp1.Color'”或任何类型。defaultValueT
0赞 Nelly 1/9/2020
@andleer,对不起,我上次对你的回答不正确。如果有人使用非枚举类型的默认值调用此函数,则此方法可能会引发 Syste.ArgumentException。在 c# 7.0 中,我无法创建 T : Enum 的 where 子句。这就是为什么我通过尝试捕捉来抓住这种可能性。
2赞 Patrik Lindström 7/1/2015 #12

我使用了类(具有解析和性能改进的 Enum 的强类型版本)。我在 GitHub 上找到了它,它也应该适用于 .NET 3.5。它有一些内存开销,因为它缓冲了字典。

StatusEnum MyStatus = Enum<StatusEnum>.Parse("Active");

这篇博文是 Enums – Better syntax, improved performance and TryParse in NET 3.5

代码:https://github.com/damieng/DamienGKit/blob/master/CSharp/DamienG.Library/System/EnumT.cs

2赞 Rae Lee 8/18/2015 #13
public static T ParseEnum<T>(string value)            //function declaration  
{
    return (T) Enum.Parse(typeof(T), value);
}

Importance imp = EnumUtil.ParseEnum<Importance>("Active");   //function call

======================完整的程序======================

using System;

class Program
{
    enum PetType
    {
    None,
    Cat = 1,
    Dog = 2
    }

    static void Main()
    {

    // Possible user input:
    string value = "Dog";

    // Try to convert the string to an enum:
    PetType pet = (PetType)Enum.Parse(typeof(PetType), value);

    // See if the conversion succeeded:
    if (pet == PetType.Dog)
    {
        Console.WriteLine("Equals dog.");
    }
    }
}
-------------
Output

Equals dog.
5赞 alhpe 10/2/2015 #14

我喜欢扩展方法解决方案..

namespace System
{
    public static class StringExtensions
    {

        public static bool TryParseAsEnum<T>(this string value, out T output) where T : struct
        {
            T result;

            var isEnum = Enum.TryParse(value, out result);

            output = isEnum ? result : default(T);

            return isEnum;
        }
    }
}

下面是我带有测试的实现。

using static Microsoft.VisualStudio.TestTools.UnitTesting.Assert;
using static System.Console;

private enum Countries
    {
        NorthAmerica,
        Europe,
        Rusia,
        Brasil,
        China,
        Asia,
        Australia
    }

   [TestMethod]
        public void StringExtensions_On_TryParseAsEnum()
        {
            var countryName = "Rusia";

            Countries country;
            var isCountry = countryName.TryParseAsEnum(out country);

            WriteLine(country);

            IsTrue(isCountry);
            AreEqual(Countries.Rusia, country);

            countryName = "Don't exist";

            isCountry = countryName.TryParseAsEnum(out country);

            WriteLine(country);

            IsFalse(isCountry);
            AreEqual(Countries.NorthAmerica, country); // the 1rst one in the enumeration
        }
33赞 Timo 12/14/2015 #15

小心:

enum Example
{
    One = 1,
    Two = 2,
    Three = 3
}

Enum.(Try)Parse() 接受多个逗号分隔的参数,并将它们与二进制 'or' |.你不能禁用它,在我看来,你几乎从不想要它。

var x = Enum.Parse("One,Two"); // x is now Three

即使没有定义,仍然会得到 int 值。更糟糕的是:Enum.Parse() 可以给你一个甚至没有为枚举定义的值!Threex3

我不想经历用户自愿或不愿意触发此行为的后果。

此外,正如其他人所提到的,对于大型枚举(即可能值的数量呈线性)而言,性能并不理想。

我提出以下建议:

    public static bool TryParse<T>(string value, out T result)
        where T : struct
    {
        var cacheKey = "Enum_" + typeof(T).FullName;

        // [Use MemoryCache to retrieve or create&store a dictionary for this enum, permanently or temporarily.
        // [Implementation off-topic.]
        var enumDictionary = CacheHelper.GetCacheItem(cacheKey, CreateEnumDictionary<T>, EnumCacheExpiration);

        return enumDictionary.TryGetValue(value.Trim(), out result);
    }

    private static Dictionary<string, T> CreateEnumDictionary<T>()
    {
        return Enum.GetValues(typeof(T))
            .Cast<T>()
            .ToDictionary(value => value.ToString(), value => value, StringComparer.OrdinalIgnoreCase);
    }

评论

6赞 pcdev 8/22/2018
事实上,这对于了解 .这意味着您可以将枚举值设置为 2 的幂,并且您有一种非常简单的方法来解析多个布尔标志,例如。“UseSSL,NoRetries,Sync”。事实上,这可能就是它的设计目的。Enum.(Try)Parse accepts multiple, comma-separated arguments, and combines them with binary 'or'
0赞 Trisped 8/15/2020
@pcdev 不确定您是否知道,但此功能是为了帮助支持 (枚举的 Flags 属性](learn.microsoft.com/en-us/dotnet/csharp/language-reference/...)。
0赞 wenn32 1/19/2022
这应该是公认的答案。重大陷阱。
4赞 Koray 6/22/2016 #16

为了提高性能,这可能会有所帮助:

    private static Dictionary<Type, Dictionary<string, object>> dicEnum = new Dictionary<Type, Dictionary<string, object>>();
    public static T ToEnum<T>(this string value, T defaultValue)
    {
        var t = typeof(T);
        Dictionary<string, object> dic;
        if (!dicEnum.ContainsKey(t))
        {
            dic = new Dictionary<string, object>();
            dicEnum.Add(t, dic);
            foreach (var en in Enum.GetValues(t))
                dic.Add(en.ToString(), en);
        }
        else
            dic = dicEnum[t];
        if (!dic.ContainsKey(value))
            return defaultValue;
        else
            return (T)dic[value];
    }

评论

2赞 12/8/2020
您还应该提供性能测试输出,例如在使用您的方法将字符串转换为枚举时运行上述代码所花费的时间,以及如果有人想在 C# 中检查字符串到枚举或枚举到字符串,请使用常规 Enum.Parse,检查 qawithexperts.com/article/c-sharp/...
2赞 isxaker 10/5/2016 #17

我发现这里没有考虑具有 EnumMember 值的枚举值的情况。所以我们开始吧:

using System.Runtime.Serialization;

public static TEnum ToEnum<TEnum>(this string value, TEnum defaultValue) where TEnum : struct
{
    if (string.IsNullOrEmpty(value))
    {
        return defaultValue;
    }

    TEnum result;
    var enumType = typeof(TEnum);
    foreach (var enumName in Enum.GetNames(enumType))
    {
        var fieldInfo = enumType.GetField(enumName);
        var enumMemberAttribute = ((EnumMemberAttribute[]) fieldInfo.GetCustomAttributes(typeof(EnumMemberAttribute), true)).FirstOrDefault();
        if (enumMemberAttribute?.Value == value)
        {
            return Enum.TryParse(enumName, true, out result) ? result : defaultValue;
        }
    }

    return Enum.TryParse(value, true, out result) ? result : defaultValue;
}

该枚举的示例:

public enum OracleInstanceStatus
{
    Unknown = -1,
    Started = 1,
    Mounted = 2,
    Open = 3,
    [EnumMember(Value = "OPEN MIGRATE")]
    OpenMigrate = 4
}
5赞 Brian Rice 11/25/2016 #18

使用 TryParse 的超级简单代码:

var value = "Active";

StatusEnum status;
if (!Enum.TryParse<StatusEnum>(value, out status))
    status = StatusEnum.Unknown;
2赞 Bartosz Gawron 2/8/2017 #19

您必须使用 Enum.Parse 从 Enum 中获取对象值,然后您必须将对象值更改为特定的枚举值。可以使用 Convert.ChangeType 强制转换为枚举值。请查看以下代码片段

public T ConvertStringValueToEnum<T>(string valueToParse){
    return Convert.ChangeType(Enum.Parse(typeof(T), valueToParse, true), typeof(T));
}
2赞 AmirReza-Farahlagha 10/1/2018 #20

试试这个例子:

 public static T GetEnum<T>(string model)
    {
        var newModel = GetStringForEnum(model);

        if (!Enum.IsDefined(typeof(T), newModel))
        {
            return (T)Enum.Parse(typeof(T), "None", true);
        }

        return (T)Enum.Parse(typeof(T), newModel.Result, true);
    }

    private static Task<string> GetStringForEnum(string model)
    {
        return Task.Run(() =>
        {
            Regex rgx = new Regex("[^a-zA-Z0-9 -]");
            var nonAlphanumericData = rgx.Matches(model);
            if (nonAlphanumericData.Count < 1)
            {
                return model;
            }
            foreach (var item in nonAlphanumericData)
            {
                model = model.Replace((string)item, "");
            }
            return model;
        });
    }

在此示例中,您可以发送每个字符串,并将 .如果您有所需的数据,请将其作为您的类型返回。EnumEnumEnum

评论

2赞 Lars Kristensen 10/1/2018
您正在覆盖每一行,因此如果它包含破折号,则不会被替换。此外,您不必检查字符串是否包含任何内容,您仍然可以调用:newModelReplacevar newModel = model.Replace("-", "").Replace(" ", "");
1赞 AmirReza-Farahlagha 10/1/2018
@LarsKristensen是的,我们可以创建一个删除非字母数字字符的方法。
1赞 AHMED RABEE 5/22/2019 #21
        <Extension()>
    Public Function ToEnum(Of TEnum)(ByVal value As String, ByVal defaultValue As TEnum) As TEnum
        If String.IsNullOrEmpty(value) Then
            Return defaultValue
        End If

        Return [Enum].Parse(GetType(TEnum), value, True)
    End Function
3赞 AHMED RABEE 5/22/2019 #22
public TEnum ToEnum<TEnum>(this string value, TEnum defaultValue){
if (string.IsNullOrEmpty(value))
    return defaultValue;

return Enum.Parse(typeof(TEnum), value, true);}
8赞 JCisar 11/28/2019 #23

不确定这是什么时候添加的,但在 Enum 类上现在有一个

Parse<TEnum>(stringValue)

与相关示例一起使用:

var MyStatus = Enum.Parse<StatusEnum >("Active")

或通过以下方式忽略大小写:

var MyStatus = Enum.Parse<StatusEnum >("active", true)

以下是它使用的反编译方法:

    [NullableContext(0)]
    public static TEnum Parse<TEnum>([Nullable(1)] string value) where TEnum : struct
    {
      return Enum.Parse<TEnum>(value, false);
    }

    [NullableContext(0)]
    public static TEnum Parse<TEnum>([Nullable(1)] string value, bool ignoreCase) where TEnum : struct
    {
      TEnum result;
      Enum.TryParse<TEnum>(value, ignoreCase, true, out result);
      return result;
    }

评论

3赞 Mariusz Pawelski 11/24/2020
这是在 .NET Core 2.0 中添加的(我在其他答案中写了一些关于它的内容)
3赞 Joel Wiklund 1/24/2020 #24

如果属性名称与要调用的名称不同(即语言差异),则可以这样做:

MyType.cs

using System;
using System.Runtime.Serialization;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;

[JsonConverter(typeof(StringEnumConverter))]
public enum MyType
{
    [EnumMember(Value = "person")]
    Person,
    [EnumMember(Value = "annan_deltagare")]
    OtherPerson,
    [EnumMember(Value = "regel")]
    Rule,
}

EnumExtensions.cs

using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;

public static class EnumExtensions
{
    public static TEnum ToEnum<TEnum>(this string value) where TEnum : Enum
    {
        var jsonString = $"'{value.ToLower()}'";
        return JsonConvert.DeserializeObject<TEnum>(jsonString, new StringEnumConverter());
    }

    public static bool EqualsTo<TEnum>(this string strA, TEnum enumB) where TEnum : Enum
    {
        TEnum enumA;
        try
        {
            enumA = strA.ToEnum<TEnum>();
        }
        catch
        {
            return false;
        }
        return enumA.Equals(enumB);
    }
}

程序.cs

public class Program
{
    static public void Main(String[] args) 
    { 
        var myString = "annan_deltagare";
        var myType = myString.ToEnum<MyType>();
        var isEqual = myString.EqualsTo(MyType.OtherPerson);
        //Output: true
    }     
}
1赞 MBWise 6/12/2020 #25

如果要在 null 或空时使用默认值(例如,从配置文件检索且该值不存在时),并在字符串或数字与任何枚举值不匹配时引发异常。不过,要注意Timo的回答中的警告(https://stackoverflow.com/a/34267134/2454604)。

    public static T ParseEnum<T>(this string s, T defaultValue, bool ignoreCase = false) 
        where T : struct, IComparable, IConvertible, IFormattable//If C# >=7.3: struct, System.Enum 
    {
        if ((s?.Length ?? 0) == 0)
        {
            return defaultValue;
        }

        var valid = Enum.TryParse<T>(s, ignoreCase, out T res);

        if (!valid || !Enum.IsDefined(typeof(T), res))
        {
            throw new InvalidOperationException(
                $"'{s}' is not a valid value of enum '{typeof(T).FullName}'!");
        }
        return res;
    }
-1赞 Felipe Augusto 4/7/2021 #26

首先,你需要装饰你的枚举,如下所示:

    public enum Store : short
{
    [Description("Rio Big Store")]
    Rio = 1
}

在 .NET 5 中,我创建了以下扩展方法:

//The class also needs to be static, ok?
public static string GetDescription(this System.Enum enumValue)
    {
        FieldInfo fi = enumValue.GetType().GetField(enumValue.ToString());

        DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(
            typeof(DescriptionAttribute), false);

        if (attributes != null && attributes.Length > 0) return attributes[0].Description;
        else return enumValue.ToString();
    }

现在,您有了一个可以在任何枚举中使用的扩展方法

喜欢这个:

var Desc = Store.Rio.GetDescription(); //Store is your Enum

评论

2赞 Panagiotis Kanavos 4/28/2021
该问题询问如何将字符串解析为枚举,而不是如何将枚举格式化为字符串
0赞 Zimano 11/10/2021
这恐怕完全没有抓住重点。
29赞 Jordan Ryder 10/20/2021 #27

在某个时候添加了 Parse 的通用版本。对我来说,这是可取的,因为我不需要“尝试”解析,而且我也希望在不生成输出变量的情况下内联结果。

ColorEnum color = Enum.Parse<ColorEnum>("blue");

MS 文档:解析

评论

8赞 WSC 6/21/2022
注意:泛型版本不作为 .NET Framework 的一部分存在。等效语法为 。ColorEnum color = (ColorEnum)Enum.Parse(typeof(ColorEnum), "blue");
14赞 Bloggrammer 2/24/2022 #28

此处的大多数答案都要求每次调用扩展方法时始终传入枚举的默认值。如果您不想采用这种方法,可以按如下方式实现它:

 public static TEnum ToEnum<TEnum>(this string value) where TEnum : struct
 {
     if (string.IsNullOrWhiteSpace(value))
          return default(TEnum);

     return Enum.TryParse(value, true, out TEnum result) ? result : default(TEnum);

 }

使用默认文本(从 C# 7.1 中提供)

 public static TEnum ToEnum<TEnum>(this string value, TEnum defaultValue = default) where TEnum : struct
 {
       if (string.IsNullOrWhiteSpace(value))
            return defaultValue ;

       return Enum.TryParse(value, true, out TEnum result) ? result : defaultValue ;

 }

更好的是:

public static TEnum ToEnum<TEnum>(this string value) where TEnum : struct
{
      if (string.IsNullOrWhiteSpace(value))
           return default;

      return Enum.TryParse(value, true, out TEnum result) ? result : default;

}

评论

0赞 bkqc 9/23/2022
在 7.1 版本上,您已经定义了 defaultValue 参数,但您似乎没有在任何地方使用它。是错误还是我遗漏了什么?
0赞 Bloggrammer 9/25/2022
好渔获。代替你可以回来defaultdefaultValue
0赞 bkqc 9/27/2022
但事实上,即使您使用 defaultValue 调用该函数,它也永远不会被使用,因为您只有 和 .不应该是吗,否则这个参数似乎是无用和未使用的。你不明白吗?此外,从 C#7.3 开始,您可以使用如下所示:learn.microsoft.com/en-us/dotnet/csharp/programming-guide/...return default: defaultreturn defaultValue: defaultIDE0060 - Remove unused parameter ‘defaultValue’ if it is not part of a shipped public APIwhere T : System.Enum
0赞 bkqc 9/27/2022
我的意思是,因为 TryParse 需要结构才能工作。where T : struct, System.Enum
0赞 Bloggrammer 9/27/2022
请仔细阅读我之前的评论。我说,“到位了,你可以回来了”。这意味着;而不是你应该有.这同样适用于我希望能帮助:)defaultdefaultValuereturn defaultreturn defaultValueTryParse(...) ? result : defaultValue;
0赞 Jared_M 7/2/2022 #29

我开始使用这种方法。性能似乎还可以,但是它需要一些样板代码设置。

public enum StatusType {
    Success,
    Pending,
    Rejected
}

static class StatusTypeMethods {

    public static StatusType GetEnum(string type) {
        switch (type) {
            case nameof(StatusType.Success): return StatusType.Success;
            case nameof(StatusType.Pending): return StatusType.Pending;
            case nameof(StatusType.Rejected): return StatusType.Rejected;
            default:
                throw new ArgumentOutOfRangeException(nameof(type), type, null);
        };
    }
}

稍后,您可以像这样使用它:

StatusType = StatusType.GetEnum("Success");