【问题标题】:How to assign string values to enums and use that value in a switch如何将字符串值分配给枚举并在开关中使用该值
【发布时间】:2011-11-01 12:02:39
【问题描述】:

基本上一系列标题将被传递到 switch 语句中,我需要将它们与枚举的字符串值进行比较。但我几乎不知道如何正确地做到这一点。

另外,我不知道这是否是最好的方法,所以如果有人有任何想法?

例如:

enum
{
    doctor = "doctor",
    mr = "mr",
    mrs = "mrs"
}

然后切换我分配给它们的字符串值。

【问题讨论】:

    标签: c# .net enums


    【解决方案1】:

    我发现对我来说最好的方法是在枚举值上使用System.ComponentModel.DescriptionAttribute 属性。

    这是一个例子:

    using System.ComponentModel;
    
    public enum ActionCode
    {
        [Description("E")]
        Edit,
        [Description("D")]
        Delete,
        [Description("R")]
        Restore
    }
    

    然后,要使用它,请在静态类上创建一个扩展方法,如下所示:

    编辑:我重写了该方法以包含来自 Laurie Dickinson 的一个很好的建议,以便该方法在没有 Description 属性时返回枚举值的名称。我还重构了该方法以尝试改进功能。它现在适用于所有枚举,无需使用 IConvertible

    public static class Extensions
    {
        public static string GetDescription(this Enum e)
        {
            var attribute =
                e.GetType()
                    .GetTypeInfo()
                    .GetMember(e.ToString())
                    .FirstOrDefault(member => member.MemberType == MemberTypes.Field)
                    .GetCustomAttributes(typeof(DescriptionAttribute), false)
                    .SingleOrDefault()
                    as DescriptionAttribute;
    
            return attribute?.Description ?? e.ToString();
        }
    }
    

    所以,要获取与我们上面的枚举关联的字符串,我们可以使用以下代码:

    using Your.Extension.Method.Namespace;
    
    ...
    
    var action = ActionCode.Edit;
    var actionDescription = action.GetDescription();
    
    // Value of actionDescription will be "E".
    

    这是另一个示例枚举:

    public enum TestEnum
    {
        [Description("This is test 1")]
        Test1,
        Test2,
        [Description("This is test 3")]
        Test3
    
    }
    

    这是查看描述的代码:

    var test = TestEnum.Test2;
    var testDescription = test.GetDescription();
    test = TestEnum.Test3;
    var testDescription2 = test.GetDescription();
    

    结果将是:

    testDescription: "Test2"
    testDescription2: "This is test 3"
    

    我想继续发布通用方法,因为它更有用。它使您不必为所有枚举编写自定义扩展。

    【讨论】:

    • 有效,但速度非常慢
    • @ceds - 同意,但代价可能是值得的。在我们的案例中,我们使用此功能的极少数地方。如果后备存储是数据库,则速度特别慢。但好处和用例是存在的。
    • 谢谢,这很有帮助。如果没有描述,我将其更新为返回枚举的名称,如果 descriptionAttribute 为 null,则返回 type.GetEnumName(val)。
    • @Laurie Dickinson - 这是个好主意。感谢分享。
    • @David Storfer 这可能不是一个坏主意,尽管我应该将其更改为 First() 并消除默认值。我相信我们几乎可以保证在这一点上有一个值,因为它是一个枚举。它不应该为空。
    【解决方案2】:

    您不能有一个基础类型为stringenumThe underlying type can be any integral type except char.

    如果您想将string 转换为您的enum,那么您可能需要使用ParseTryParse 方法。

    string incoming = "doctor";
    
    // throws an exception if the string can't be parsed as a TestEnum
    TestEnum foo = (TestEnum)Enum.Parse(typeof(TestEnum), incoming, true);
    
    // try to parse the string as a TestEnum without throwing an exception
    TestEnum bar;
    if (Enum.TryParse(incoming, true, out bar))
    {
        // success
    }
    else
    {
        // the string isn't an element of TestEnum
    }
    
    // ...
    
    enum TestEnum
    {
        Doctor, Mr, Mrs
    }
    

    【讨论】:

      【解决方案3】:

      我想为使用 C# 6 或更高版本的任何人添加另一个答案。

      如果您只想获取 Enum 值的名称,可以使用 C# 6 中引入的新 nameof() 方法。

      string enumName = nameof(MyEnum.EnumVal1); // enumName will equal "EnumVal1"
      

      虽然乍一看这似乎有点过头了(为什么不直接将字符串的值设置为“EnumVal1”呢?),但它会为您提供编译时检查以确保该值有效。因此,如果您更改了枚举值的名称而忘记告诉您的 IDE 查找和替换所有引用,则在您修复它们之前它不会编译。

      【讨论】:

        【解决方案4】:

        这不是应该硬编码的东西。它应该是数据驱动的,可能从外部文件或数据库中读取。您可以将它们存储在 Dictionary 中并使用密钥来驱动您的逻辑。

        【讨论】:

        • 硬编码枚举描述并不比在现实世界中的域对象之后命名类更不正确。有时 Fish.BabelFish 将永远是“Babel 鱼”。可以从本地化资源中获取值(用于全球化),但您不必从数据库或外部文件中获取每条信息。
        • @Michael Earls - 应用程序来来去去,但数据永远存在。如果将其放入数据库中,则可以从任意数量的应用程序中使用它。 asktom.oracle.com/pls/asktom/…
        • @dcp - 好点。感谢您的链接。内容非常丰富。
        • 很难根据 OP 中的示例文本做出这种评估。也许这只是他为了阐明自己的观点而拼凑起来的一个简单示例,但实际上他会使用更适合此解决方案的东西。我将它用于 cookie 类型/名称。字典不是强类型的,所以对我来说这是个坏主意。
        【解决方案5】:

        我认为执行此操作的标准方法是使用具有只读字符串属性的静态类,该属性返回您想要的值。

        【讨论】:

          【解决方案6】:

          枚举不能是字符串类型。

          允许的枚举类型为 byte、sbyte、short、ushort、int、uint、long 或 ulong。

          http://msdn.microsoft.com/en-us/library/sbbt4032.aspx

          【讨论】:

          • 我没有说我希望它是字符串类型的。我说我想给它分配一个字符串值。我以前看过它,想知道如何实现它。
          • 我很抱歉,我把它读成同样的东西,因为基础值是枚举的类型。
          【解决方案7】:

          枚举只能具有整数基础类型(char 除外)。因此你不能做你想做的事,至少不能直接做。

          但是你可以将你拥有的字符串翻译成枚举类型:

          EnumType eVal = (EnumType)Enum.Parse(typeof(EnumType), strValue);
          
          switch(eVal)
          {
              case EnumType.doctor:/*...*/; break;
              case EnumType.mr: /*...*/; break;
          }
          

          【讨论】:

            【解决方案8】:

            为什么不只使用纯枚举和开关?

            enum Prefix
            {
                doctor,
                mr,
                mrs
            }
            

            然后你可以使用就像

            string case = "doctor";
            
            switch ((Prefix)Enum.Parse(typeof(Prefix), "doctor"))
            {
                case Prefix.doctor:
                    ...
                    break;
                ...
                default:
                    break;
            }
            

            【讨论】:

            • 枚举必须是一个单词,例如 Lance Corporal 会给我带来麻烦
            • 你可以创建一个映射Dictionary<string, Prefix> map,填充它,然后给一个字符串“Lance Corporal”,找到一个合适的枚举值(比如Prefix p = map["Lance Corporal"];),然后切换枚举类型。跨度>
            【解决方案9】:

            只是分享我的解决方案。通过下载 nuget 包 Extension.MV,可以使用一种方法从枚举描述中获取字符串

            public enum Prefix
            {
                [Description("doctor")]
                doctor = 1,
                [Description("mr")]
                mr = 2,
                [Description("mrs")]
                mrs = 3
            }
            
            public static class PrefixAdapter {
            
                public static string ToText(this Prefix prefix) {
                    return prefix.GetEnumDescription();
                }
            
                public static Prefix ToPrefix(this string text) {
                    switch (text)
                    {
                        case "doctor"
                            return Prefix.doctor;
                        case "mr"
                            return Prefix.mr;
                        case "ms"
                            return Prefix.mrs;
                    }
                }
            }
            

            【讨论】:

              【解决方案10】:

              阅读this tutorial 以了解枚举的工作原理。还有switch 语句的例子。

              【讨论】:

              • 我浏览了一下,但没有看到任何关于在那里分配字符串值的信息。
              【解决方案11】:

              如果你真的是铁杆并且使用 c# 8...

              public static string GetDescription(this VendorContactType enumval) =>
                      enumval switch {
                          VendorContactType.AccountContact => "Account Contact",
                          VendorContactType.OrderContact => "Order Contact",
                          VendorContactType.OrderContactCC => "Order Contact CC",
                          VendorContactType.QualityContact => "Quality Contact",
                          VendorContactType.ShippingContact => "Shipping Contact",
                          _ => ""
                      };
              

              我意识到这不会接受您程序的所有枚举,但这是我使用的并且我喜欢它。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2021-07-24
                • 1970-01-01
                • 2021-09-10
                • 2021-10-21
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多