枚举项映射到另一个值

5

我有一个枚举:

enum MyEnum{
    aaaVal1,
    aaaVal2,
    aaaVal3,
}  

我需要一个缩写版本的'MyEnum',它将'MyEnum'中的每个项目映射到不同的值。 我目前的方法是使用简单的方法来翻译每个项目:

string translate(MyEnum myEnum)
{
    string result = "";
    switch ((int)myEnum)
    {
        0:   result = "abc";
        1:   result = "dft";
        default: result = "fsdfds"
    }
    return result;
}

这种方法的问题在于,每次程序员更改MyEnum时,他还应该更改翻译方法。这不是一种好的编程方式。

那么,有没有更优雅的解决方案呢?

谢谢 :-)


你在使用.NET吗?我有一个不错的解决方案,但需要一些库。 - Vladislav Qulin
可能是创建键值为字符串的枚举的重复问题。 - Felix K.
4个回答

9
四个选项:
  • Decorate your enum values with attributes, e.g.

    enum MyEnum
    {
        [Description("abc")]
        AaaVal1,
        [Description("dft")]
        AaaVal2,
        AaaVal3,
    } 
    

    Then you can create a mapping (like the dictionary solution below) via reflection.

  • Keep the switch statement but switch on the enum value instead of a number for better readability:

    switch (myEnum)
    {
        case MyEnum.AaaVal1: return "abc";
        case MyEnum.AaaVal2: return "dft";
        default:             return "fsdfds";
    }
    
  • Create a Dictionary<MyEnum, string>:

    private static Dictionary<MyEnum, string> EnumDescriptions = 
        new Dictionary<MyEnum, string>
    {
        { MyEnum.AaaVal1, "abc" },
        { MyEnum.AaaVal2, "dft" },        
    };
    

    You'd need to handle the defaulting in the method, of course.

  • Use a resource file, with an entry for each string representation. This would be better if you're really trying to translate in a way that might need different translations for different cultures.


2

考虑到在枚举类型上使用描述符是相当常见的,因此这里提供一个足够好的类来实现它:

[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
class EnumDescriptor : Attribute
{
    public readonly string Description;

    public EnumDescriptor(string description)
    {
        this.Description = description;
    }

    public static string GetFromValue<T>(T value) where T : struct
    {
        var type = typeof(T);
        var memInfo = type.GetField(value.ToString());
        var attributes = memInfo.GetCustomAttributes(typeof(EnumDescriptor), false);

        if (attributes.Length == 0)
        {
            return null;
        }

        return ((EnumDescriptor)attributes[0]).Description;
    }
}

enum MyEnum
{
    [EnumDescriptor("Hello")]
    aaaVal1,
    aaaVal2,
    aaaVal3,
}  

string translate(MyEnum myEnum)
{
    // The ?? operator returns the left value unless the lv is null,
    // if it's null it returns the right value.
    string result = EnumDescriptor.GetFromValue(myEnum) ?? "fsdfds";
    return result;
}

不完全正确 - 你需要 MyEnum.aaaVal1 等。 - Jon Skeet

1
我发现你试图做的有点奇怪。如果你要进行翻译,那么你应该创建一个RESX文件并创建实际的翻译。但是回答你的问题,我想你可以创建另一个具有相同数量字段和相同编号(如果你使用的不是默认值)的枚举,并将其作为缩写名称。连接两者应该很简单:
string GetAbbreviation(Enum1 enum1)
{
  return ((Enum2)((int)enum1)).ToString();
}

我认为他想要的不完全是一种翻译,而是说他有一个CompareResuleEnum { Equal, OnlyAtSrc, OnlyAtTgt },但当他向用户显示结果时,他希望有一个更好的显示名称,例如Equal =“对象相同”。 - Tomer W
@TomerW 这仍然是一种翻译。因为您将根据用户的语言显示不同的内容。 - MBender

1

属性将是这种情况的好解决方案。您可以通过声明方式指定枚举成员的翻译:

public class TranslateAttribute
{
    public string Translation { get; private set; }

    public TranslateAttribute(string translation)
    {
        Translation = translation;
    }
}

enum MyEnum
{
    [Translate("abc")]
    aaaVal1,

    [Translate("dft")]
    aaaVal2,

    [Translate("fsdfds")]
    aaaVal3
} 

在此之后,您应该编写获取翻译的通用方法。它应该通过反射检查带有翻译属性的内容,并在指定了翻译时返回翻译结果,在其他情况下返回默认值。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接