为枚举元素指定多个值

时间:2010-12-21 19:17:14

标签: c# enums

嗨,我现在有这个枚举

[Serializable]
public enum Country
{
    US      = 1,
    Canada  = 2,
}

当我通常从数据库中获取整数时,我使用

将其转换为枚举
(Country) Convert.ToInt32("1")

我现在在美国和加拿大有2个子区域,1& 2为美国,3& 4为加拿大。所以当我做的时候

(Country) Convert.ToInt32("1")(Country) Convert.ToInt32("2")我应该让枚举成为美国。并为3& 4加拿大。我该如何实现?

[Serializable]
public enum Country
{
    US      = 1,2
    Canada  = 3,4
}

像这样的东西。这可能不对,只是为了给你一个想法。

9 个答案:

答案 0 :(得分:13)

enum可能不是模拟此类问题的正确构造。

我建议创建一个表示国家/地区信息的类,并提供转换为数字表示的方法。对于这样的问题,您还必须确定在将选定的Country实例转换为数值时将使用的编码值。

Enum对象模式可以为建模此类情况提供有用的起点:

public sealed class Country
{
    // initialize appropriately in the constructor...
    private readonly int[] m_Values;
    private readonly string m_Name;

    // make the constructor private so that only this class can set up instances
    private Country( string name, int[] codes ) { ... }

    public static Country US = new Country("United States", new[]{ 1,2 } );
    public static Country Canada = new Country("Canada", new[] {3,4} );

    public static Country FromCode( int code ) { ... }
    public override string ToString() { return m_Name; }
    // ... etc...
}

根据您的示例,您还应该考虑是否需要将Country子区域建模为第一类实体,而不是简单地将它们折叠到Country枚举的实现细节中。是否您是否应该这样做取决于您的要求和用例,因此只有您可以做出适当的决定。

答案 1 :(得分:10)

这是不可能的。那你必须使用单独的值。如果名称相同,即

[Serializable]
[Flags]
public enum Country
{
    US      = 1,
    Canada  = 2,
    Northern = 4,
    Southern = 8
}

你可以这样做:Countries = Country.US | Country.Northern。如果没有,你需要找到另一种方式,可能是另一种方式,甚至更好,Location类。

答案 2 :(得分:9)

你必须做这样的事情:

class Region
{
    static readonly RegionMap = new Dictionary<int,string>
    {
        { 1, "US" },
        { 2, "US" },
        { 3, "Canada" }
        { 4, "Canada" }
    }

    public static string GetRegion(int code)
    {
        string name;
        if (!RegionMap.TryGetValue(code, out name)
        {
            // Error handling here
        }
        return name;
    }
}

然后根据数据库中的值查找字符串:

string region = Region.GetRegion(dbVal);

答案 3 :(得分:5)

也许是这样的?

static Country ConvertRegionToCountry(string region)
{
    switch (region)
    {
        case "1":
        case "2":
            return Country.US;

        case "3":
        case "4":
            return Country.Canada;
    }
}

答案 4 :(得分:3)

啊我刚刚使用了一个函数而不是直接进行类型转换。实现完全不同的东西要容易得多。我已经有很多代码在运行,因此无法改变它,但这就是我所做的。

public Country GetCountryByTaxID(int taxID)
        {
            if (taxID == 3 || taxID == 4)
            {
                return Country.USA;
            }
            else 
            {
                return Country.Canada;
            }
        }  

答案 5 :(得分:3)

public Country GetCountry(int a)
        {
            if (a == 1 || a == 2)
            {
                return Country.USA;
            }
            else if (a ==  4|| a == 3)
            {
                return Country.Canada;
            }
        }  

答案 6 :(得分:0)

这对于我来说就像一个固定的问题,1&amp; 2是在我们和3&amp; 4在加拿大。 code project上有一些设置代码,我认为这样可以更好地模拟问题。

答案 7 :(得分:0)

除了dtb的答案(以及那些等效的if建议)之外,我刚刚在我的应用程序命名空间中实现了System.Convert的“重写”版本:

public static class Convert
{
    public static object ChangeType
        (object value, Type conversionType, IFormatProvider provider)
    {
        int country;
        if (conversionType == typeof(Country)
            && int.TryParse(value.ToString(), out country))
        {
            switch (country)
            {
                case 1:
                case 2:
                    return Country.US;
                case 3:
                case 4:
                    return Country.Canada;
            }
        }

        // For most cases, including any country unmatched above...
        return System.Convert.ChangeType(value, conversionType, provider);
    }
}

mscorlib.dll Convert类的原始方法当然必须以“System.”为前缀,因此欢迎任何改进!

答案 8 :(得分:0)

我一直在寻找答案,因为我处于类似的情况(我需要枚举来定义游戏的菜单状态,其中每个状态更改都涉及更改多个对象)。但是我很难找到比我目前使用的更适合我需求的答案。所以我会把它留在这里给觉得有用的人。

只要您在枚举中处理数值,就可以使用位移位的“复合”值。本质上,

  • 2 个字节作为 ushort(0x1234 作为 0x120x34
  • 2 个 ushorts 作为 uint32(0x12345678 作为 0x12340x5678
  • 2 个 uint 作为一个 ulong(0x0123456789ABCDEF 作为 0x012345670x89ABCDEF
  • 8bytes 作为一个 ulong(希望你明白我的意思)

等等。

示例:

public enum CompoundEnum: ushort
{
    MenuOneOne = 0x101, // Can be split into bytes 0x1 and 0x1
    MenuOneTwo = 0x102, // Can be split into bytes 0x1 and 0x2
    MenuTwoOne = 0x201, // Can be split into bytes 0x2 and 0x1
}

我不太了解负值如何存储在不同的系统中,但我猜任何对负值存储有足够了解的人也可以轻松地“复合”有符号值。此外,我个人的偏好是使用十六进制表示,因为这样更容易直观地读取单独的值。

关于如何使用位移计算值已经足够了(至少我希望它被称为位移),所以我只是将这个答案链接到这里:https://stackoverflow.com/a/3099367/1543356