【问题标题】:String to enum conversion in C#C#中字符串到枚举的转换
【发布时间】:2009-07-27 08:36:39
【问题描述】:

我有一个组合框,其中显示了一些条目,例如:

Equals
Not Equals 
Less Than
Greater Than

请注意,这些字符串包含空格。我定义了一个与这些条目匹配的枚举,例如:

enum Operation{Equals, Not_Equals, Less_Than, Greater_Than};

由于不允许空格,所以我使用了_字符。

现在,有没有什么方法可以将给定的字符串自动转换为枚举元素,而无需在 C# 中编写循环或一组 if 条件?

【问题讨论】:

标签: c# enums


【解决方案1】:

我建议构建一个Dictionary<string, Operation> 将友好名称映射到枚举常量,并在元素本身中使用正常的命名约定。

enum Operation{ Equals, NotEquals, LessThan, GreaterThan };

var dict = new Dictionary<string, Operation> {
    { "Equals", Operation.Equals },
    { "Not Equals", Operation.NotEquals },
    { "Less Than", Operation.LessThan },
    { "Greater Than", Operation.GreaterThan }
};

var op = dict[str]; 

或者,如果你想坚持你目前的方法,你可以这样做(我不建议这样做):

var op = (Operation)Enum.Parse(typeof(Operation), str.Replace(' ', '_'));

【讨论】:

  • 出于兴趣,您为什么不建议使用 Enum.Parse?更多转化?
  • 我不反对Enum.Parse 方法。我反对将用户界面字符串与代码元素紧密耦合(并根据显示名称更改代码)。
【解决方案2】:
Operation enumVal = (Operation)Enum.Parse(typeof(Operation), "Equals")

对于“不等于”,你需要在上面的语句中用下划线替换空格

编辑:以下版本在尝试解析之前将空格替换为下划线:

string someInputText;
var operation = (Operation)Enum.Parse(typeof(Operation), someInputText.Replace(" ", "_"));

【讨论】:

  • 不会将“不等于”匹配到 Operation.Not_Equals
  • 这就是为什么我说你需要对值进行替换以用下划线替换空格,以便匹配...
【解决方案3】:

要么使用字典(根据 Mehrdad 的回答)创建专用映射器,要么实现 TypeConverter

您的自定义 TypeConverter 可以替换 " " -&gt; "_"(反之亦然),也可以反映枚举并使用属性来确定项目的显示文本。

enum Operation
{
    [DisplayName("Equals")]
    Equals, 

    [DisplayName("Not Equals")]
    Not_Equals, 

    [DisplayName("Less Than")]
    Less_Than, 

    [DisplayName("Greater Than")]
    Greater_Than
};

public class OperationTypeConverter : TypeConverter
{
    private static Dictionary<string, Operation> operationMap;

    static OperationTypeConverter()
    {
        BindingFlags bindingFlags = BindingFlags.Static | BindingFlags.GetField
            | BindingFlags.Public;

        operationMap = enumType.GetFields(bindingFlags).ToDictionary(
            c => GetDisplayName(c)
            );
    }

    private static string GetDisplayName(FieldInfo field, Type enumType)
    {
        DisplayNameAttribute attr = (DisplayNameAttribute)Attribute.GetCustomAttribute(typeof(DisplayNameAttribute));

        return (attr != null) ? attr.DisplayName : field.Name;
    }

    public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
    {
        string stringValue = value as string;

        if (stringValue != null)
        {
            Operation operation;
            if (operationMap.TryGetValue(stringValue, out operation))
            {
                return operation;
            }
            else
            {
                throw new ArgumentException("Cannot convert '" + stringValue + "' to Operation");
            }
        }
    }
}

可以通过多种方式改进此实现:

【讨论】:

  • 似乎缺少一些东西...从未声明 enumType,GetDisplayName 使用一个参数调用但声明了 2 个参数。
  • 更正:在静态构造函数中从未声明 enumType
  • 您似乎也不能在枚举声明中使用 DisplayName 属性
  • 使用 Description 属性而不是 DisplayName stackoverflow.com/questions/4367723/…
【解决方案4】:

你可以使用 Parse 方法:

 Operarion operation = (Operation)Enum.Parse(typeof(Operation), "Not_Equals");

一些例子here

【讨论】:

    【解决方案5】:

    为什么要使用另一种方式:将枚举转换为字符串?

    只需从您的枚举中生成组合框的项目。

    【讨论】:

      【解决方案6】:

      在 C# 中,您可以为枚举类型添加扩展方法。看 http://msdn.microsoft.com/en-us/library/bb383974.aspx

      您可以使用这种方法将 toString(Operation op)、fromString(String str) 和 toLocalizedString(Operation op) 方法添加到您的枚举类型。您用于查找特定字符串的方法取决于您的应用程序,并且应该与您在类似情况下所做的一致。只要您的应用不需要完全本地化,使用其他人建议的字典似乎是一个不错的首选方法。

      【讨论】:

        【解决方案7】:

        我会使用这个enum mapper class 的单例,它的执行速度比 Enum.Parse 快得多(它使用反射并且非常慢)。 然后您可以使用EnumFromString(typeof(YourEnum), "stringValue") 获取您的枚举。

        【讨论】:

          【解决方案8】:

          从 C# 8 开始,您可以使用开关来做到这一点。在您的示例中,我相信代码会是这样的。

          enum Operation{Equals, Not_Equals, Less_Than, Greater_Than};
          
          public static string OperationString(Operation opString) =>
              opString switch
              {
                  Operation.Equals => "Equals",
                  Operation.Not_Equals => "Not Equals",
                  Operation.Less_Than=> "Less Than",
                  Operation.Greater_Than=> "Greater Than",
                  _   => throw new ArgumentException(message: "invalid enum value", paramName: nameof(opString )),
              };
          

          有关文档,请参阅 here

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2015-06-10
            • 1970-01-01
            • 1970-01-01
            • 2010-09-06
            • 1970-01-01
            • 1970-01-01
            • 2012-08-25
            相关资源
            最近更新 更多