tHeSiD
tHeSiD

Reputation: 5333

Assign multiple values to enum elements

Hi I have this enum currently

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

When I usually get the integer from the database I convert it to the enum using

(Country) Convert.ToInt32("1")

I now have 2 sub regions in US and Canada, 1 & 2 for US and 3&4 for canada. So when I do

(Country) Convert.ToInt32("1") or (Country) Convert.ToInt32("2") i should get the enum to be US. and for 3 & 4 Canada. How do i implement this?

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

Something like this. This is probably not right but just to give you an Idea.

Upvotes: 19

Views: 82314

Answers (9)

Glitch
Glitch

Reputation: 595

I was looking for an answer since I am in a similar situation (I need enums to define menu states for a game where each state change involves changing multiple objects). But I'm having a hard time finding an answer that suits my needs better than what I'm using currently. So I'm just going to leave it here for whoever finds it useful.

As long as you're dealing with numerical values in your enum, you can use bit-shifted 'compound' values. Essentially,

  • 2 bytes as a ushort (0x1234 as 0x12 and 0x34)
  • 2 ushorts as a uint32 (0x12345678 as 0x1234 and 0x5678)
  • 2 uints as a ulong (0x0123456789ABCDEF as 0x01234567 and 0x89ABCDEF)
  • 8bytes as a ulong (you get my point, hopefully)

and so on.

An example:

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
}

I'm not very knowledgeable about how negative values are stored in different systems, but I'm guessing anyone with sufficient knowledge about storage of negatives can easily 'compound' signed values as well. Also, my personal preference is representation using hexadecimal, as this way it's easier to visually read the separate values.

There's enough about how to calculate values using bit-shifting (at least I hope it's called bit-shifting), so I'm just going to link this answer here: https://stackoverflow.com/a/3099367/1543356

Upvotes: 0

Hotmail Scarlet
Hotmail Scarlet

Reputation: 31

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

Upvotes: 3

mosi
mosi

Reputation: 247

Further to dtb's answer (and those equivalent if suggestions), I just implemented an 'overridden' version of System.Convert in my application's namespace:

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);
    }
}

Original methods of the mscorlib.dll Convert class must now be prefixed with "System." of course, so any refinements would be welcome!

Upvotes: 0

tHeSiD
tHeSiD

Reputation: 5333

Ah I just used a function instead of directly typecasting. Far more easier than to implement something entirely different. I already have lot of code running on this so cant change it much but here is what I did.

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

Upvotes: 4

rerun
rerun

Reputation: 25495

This seams like a set problem to me where 1 & 2 are in the set us and 3 & 4 are in the set Canada. There is some set code on code project which I think better models the problem.

Upvotes: 0

LBushkin
LBushkin

Reputation: 131646

An enum may not be the right construct to model this kind of problem.

I would suggest creating a class to represent country information, and provide methods the convert to and from numeric representations. With problems like this, you also have to decide what coding value you will use when converting a selected Country instance into a numeric value.

The Enum Object pattern can be helpful starting point for modeling this kind of situation:

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...
}

Based on your example, you should also consider whether you need to model Country sub-regions as first-class entities, rather than simply folding them into the implementation details of your Country enumeration. Whether you should do this or not depends on your requirements and use cases, so only you can make an appropriate decision on that.

Upvotes: 15

dtb
dtb

Reputation: 217233

Maybe something like this?

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

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

Upvotes: 6

Femaref
Femaref

Reputation: 61427

This is not possible. You'd have to use seperate values then. If the names are the same, ie.

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

You could do this: Countries = Country.US | Country.Northern. If not, you need to find another way, possible another property or even better, a Location class.

Upvotes: 15

Andrew Hare
Andrew Hare

Reputation: 351456

You will have to do something like this:

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;
    }
}

Then look up the string based on the value from the database:

string region = Region.GetRegion(dbVal);

Upvotes: 14

Related Questions