仅使用枚举的第一个字符转换为枚举

本文关键字:枚举 字符 转换 第一个 | 更新日期: 2023-09-27 17:56:33

我有以下枚举:

public enum GenderContract
{
    Male,
    Female,
    Unknown
}

但我从客户那里得到了"M"、"F"和"U"的值。

是否有从枚举的第一个字符转换为实际枚举项的通用方法? (假设名称没有冲突?

我有几个这样的场景,我希望能够有一种通用的方法将部分匹配转换为枚举(而不仅仅是执行 switch 语句或类似的事情)。

仅使用枚举的第一个字符转换为枚举

简短的解决方案是使用"M"、"F"和"U"的字符值

public enum GenderContract
{
    Male = 77, // 'M'
    Female = 70, // 'F'
    Unknown = 80 // 'U'
};

然后你只需要做

GenderContract c1 = (GenderContract)'M';
GenderContract c2 = (GenderContract)'F';
GenderContract c3 = (GenderContract)'U';

与其依赖实际的枚举名称,不如考虑使用 DisplayAttribute。 使用此选项意味着枚举值与字符串值不紧密绑定。 (也就是有人将女性更改为女性不会破坏价值)。

public enum GenderContract
{
  [Display(ShortName="M")]
  Male,
  [Display(ShortName="F")]
  Female,
  [Display(ShortName="U")]
  Unknown
}

然后是一个简单的扩展方法:

public static class EnumExtensions
{
    public static TAttribute GetAttributeOrDefault<TAttribute>(this Enum enumVal)
        where TAttribute : Attribute
    {
        var type = enumVal.GetType();
        var memInfo = type.GetMember(enumVal.ToString());
        var result = memInfo[0].GetCustomAttributes(typeof(TAttribute), false)
            .FirstOrDefault() as TAttribute;
        return result;
    }
    public static string ToName(this Enum value)
    {
        var result = value.ToString();
        var attribute = value.GetAttributeOrDefault<DisplayAttribute>();
        if (attribute != null)
        {
            result = attribute.Name;
        }
        return result;
    }
    public static string ToShortName(this Enum value)
    {
        var result = value.ToString();
        var attribute = value.GetAttributeOrDefault<DisplayAttribute>();
        if (attribute != null)
        {
            result = attribute.ShortName;
        }
        return result;
    }
}

用法:

Console.WriteLine(GenderContract.Male.ToShortName());

结果:

我认为

,一个简单的方法是使用这样的字典

var lookupTable = Enum.GetValues(typeof(GenderContract)).Cast<GenderContract>()
                  .ToDictionary(x => x.ToString()[0], x => x);

然后,它只是一个查找。

GenderContract e = lookupTable['M'];

我会以不同的方式做。由于您本质上需要一个查找表, 我会使用字典。 Dictionary<char, tuple<string, int>> char将是字典的关键;M,U,F。 从我的评论。

然后元组看起来像,Tuple<string, int> tuple = new Tuple<string, int> { {"Male", 0}, {"Unknown", 1}, {"Female", 2} }.然后,您可以通过以下方式访问所需的任何内容,myDictionaryTuple['U'].Item2将返回 Unknown = 1 的整数值。

例:

Dictionary<char, Tuple<string, int>> myDictionaryTuple = new Dictionary<char, Tuple<string, int>> { {'M', new Tuple<string, int>("Male", 0)}, {'F', new Tuple<string, int>("Female", 1) }, {'U', new Tuple<string, int>("Unknown", 2)}};
Console.WriteLine(myDictionaryTuple['U'].Item1); // Results in "Unknown"
Console.WriteLine(myDictionaryTuple['U'].Item2); // Results in 1
Console.WriteLine(myDictionaryTuple['U']); // Results in "(Unknown, 1)"

仅对于英语,您可以将枚举映射到 {enumValue, enumValue.ToString()} 对的列表,并在字符串的前缀上进行匹配。

var allValues = Enum.GetValues(typeof(GenderContract))
    .Cast<GenderContract>()
    .Select(x => new {Value = x, Text = x.ToString()});
var result = allValues
   .FirstOrDefault(x => x.Text.StartsWith("F", StringComparison.OrdinalIgnoreCase));
return result != null ? result.V : default(GenderContract);

如果需要更多可本地化的解决方案,可以在类似的代码中按名称将枚举值映射到资源字符串。 即具有具有GenderContract_Male名称的资源字符串,并通过"枚举类型+枚举值"查找字符串;

这是我想出的通用方法:

void Main()
{
    Console.WriteLine("M".SearchEnum<GenderContract>());
}
public static class EnumHelpers
{
   public static T SearchEnum<T>(this string value)
   {
       if (value == null)
          return default(T);
       // Get the string names for the Enum
       List<string> enumStrings = Enum.GetNames(typeof (T)).ToList();
       string matchingEnumString = enumStrings.FirstOrDefault(x => x.StartsWith(value));
       if (matchingEnumString == null)
          throw new ArgumentException("Cannot convert " + value + 
                                      " to enum of " + typeof(T).FullName );
       return ParseEnum<T>(matchingEnumString);
   }
   public static T ParseEnum<T>(this string value)
   {
       if (value == null)
          return default(T);
       return (T)Enum.Parse(typeof(T), value, true);
   }
}
public enum GenderContract
{
   Male,
   Female,
   Unknown
}
每次调用枚举时,这都会枚举枚举

的名称,因此通过以某种方式存储枚举列表可能会提高性能,但我不需要那么多性能。

此外,如果有人更改我的枚举值,那么我的代码将失败,但我接受此解决方案的风险。