Reputation: 5333
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
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,
0x1234
as 0x12
and 0x34
)0x12345678
as 0x1234
and 0x5678
)0x0123456789ABCDEF
as 0x01234567
and 0x89ABCDEF
)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
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
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
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
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
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
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
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
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