I have two very similar but not identical C# objects. I am copying the values from one class to another.
Each class has some properties that expose an enumeration type. The inside of the enumerations are the same but the names are different e.g.
public enum EnumA
{
A,
B
}
public EnumA EnumAProperty
{
get{ return enumA;}
}
public enum EnumB
{
A,
B
}
public EnumB EnumBProperty
{
get{ return enumB;}
}
I want to assign the value returned from EnumBProperty to EnumAProperty is this possible?
You can do via casting but I would not recommend it as it is fragile — if any of the enum members are reordered or new items added the result may not be what you expect.
EnumAProperty = (EnumA) EnumBProperty;
Even worse with the casting is if you have items in your source enum with no equivalent in the destination — below there are more colours than shapes:
enum Color { Red = 0, Yellow = 1, Blue = 2 };
enum Shape ( Square = 0, Triangle = 1 };
Color color = Color.Red;
Shape shape = (Shape) color;
shape could end up with the value 2 even though this value is not defined.
Instead, I'd suggest you use a switch statement to map:
EnumAProperty = ConvertToA(EnumBProperty);
...
private static EnumA ConvertToA(EnumBProperty b)
{
switch (b)
{
case EnumB.Flannel: return EnumA.HandTowel;
case EnemB.Vest: return EnumA.UnderShirt;
...
default: throw new ArgumentOutOfRangeException("b");
}
}
Each enum member has a corresponding integer value.
By default, these values are assigned in ascending order, starting with 0.
If the order of the items in the enums (and thus their numeric values) are the same, you can just cast the numeric value to EnumB to get the EnumB member with the same value:
EnumBProperty = (EnumB)(int)EnumAProperty;
If not, you need to re-parse it:
EnumBProperty = (EnumB)Enum.Parse(typeof(EnumB), EnumAProperty.ToString());
As long as both enum's of different types you can'not assign it directly.
You can define integer offset for an items so you can assign values through the integer value
public enum EnumA
{
A = 0,
B = 1
}
public enum EnumB
{
A = 0,
B = 1
}
EnumBPropertry = (int)EnumAProperty
You could either cast it to an integer or convert it to a string and then do an Enum.Parse on it.
Try the following:
EnumAProperty = (EnumA)Enum.Parse(typeof(EnumA), EnumBProperty.ToString);
EnumBProperty = (EnumB)Enum.Parse(typeof(EnumB), EnumAProperty.ToString());
Related
I have types that have a bitwise value [1,2,4,8,16,32] that are selected from checkboxes, when saving to the database i combine the selected values and get a value of 42 for instance. How can i calculate which values were selected from the combined value, on an edit screen i want to recheck the values that were selected.
To check whether e.g. 8 is contained in your combined value, you can use the bitwise and operator like this:
int combinedValue = 42;
int bitwiseValue = 8;
bool isBitwiseValueChecked = (combinedValue & bitwiseValue) == bitwiseValue;
Use an enum to model the flags:
public static void Main()
{
Console.WriteLine((MyFlags)1); // Foo
Console.WriteLine((MyFlags)7); // Foo, Bar, Baz
Console.WriteLine((int)(MyFlags.Foo | MyFlags.Bar)); // 3
}
[Flags]
enum MyFlags
{
Foo = 1,
Bar = 2,
Baz = 4
}
Then, to list all members, see List all bit names from a flag Enum
I have a number of enums that contain long lists that do change from time to time
public MyEnumType MyEnum
{
None = 0,
Option1 = 1,
Option2 = 2,
etc..
}
When they change, I need to renumber the index as invariably new options are placed inbetween existing options.
The question is, if I remove the index, will the enum always honour the order from top to bottom?
public MyEnumType MyEnum
{
None,
Option1,
Option2,
etc..
}
Thanks in advance.
Yes they will.
You can also specify just the first element if you want to make sure that values start at some specific value:
public MyEnumType MyEnum
{
None = 1,
Option1, // -> 2
Option2, // -> 3
}
For other details, check the docs.
Note that in most scenarios, your code should not care about the exact numeric values.
Situations when you do care are e.g. if you declare an enum which is an alias for an external type (e.g interop) so you need to ensure that values are the same. Another scenario is when the enumeration represents binary flags, then you want something like:
[Flags]
public MyEnumType MyEnum
{
None = 1,
Option1 = 2,
Option2 = 4
}
Simplest answer would be "Yes"... they will always honor the order.
So you no need to put index number.
public MyEnumType MyEnum
{
None,
OptionA,
OptionB,
OptionC,
...
...
OptionZ
}
this will always same as -
public MyEnumType MyEnum
{
None = 0,
OptionA = 1,
OptionB = 2,
OptionC = 3,
...
...
OptionZ = 26
}
If you introduce new enum type in between like -
public MyEnumType MyEnum
{
None,
OptionA,
OptionB,
OptionC,
...
...
OptionO
OptionNew
OptionP
...
...
OptionZ
}
Then above will be equivalent to -
public MyEnumType MyEnum
{
None = 0,
OptionA = 1,
OptionB = 2,
OptionC = 3,
...
...
OptionO = 15
OptionNew = 16
OptionP = 17
...
...
OptionZ = 27
}
Yes they honour the order, starting from the default value for int, which is zero.
If you are regularly renumbering things then it is better to explicitly assign values to the enum members, and then re-number the items when the underlying list that it is based on changes.
If you use explicit numbering then you can also insert new items into the list between existing items at any time, although you do need to be careful that you don't assign two items to the same value (which is totally legal in C#, but may produce errors if you didn't intend it).
From the C# language specification 1.10 Enums:
... When an enum member declaration does not explicitly specify a value,
the member is given the value zero (if it is the first member in the
enum type) or the value of the textually preceding enum member plus
one.
So the same as your explicit declaration here:
public MyEnumType MyEnum
{
None = 0,
Option1 = 1,
Option2 = 2,
etc..
}
By default they will count up from zero in the order they are declared.
If you define one explicitly, then the subsequent values continue counting up, using the explicit value as a seed.
I currently have an enum defined as follows:
public enum ColorEnum { Red, White, Blue, Green };
Each of these enum values has an underlying int value that I need to be able to return to the user. To do so, I wrote a function that takes in the enum and returns an int:
public int colorToValue(ColorEnum color)
{
switch (color)
{
case Red:
return 5;
case White:
return 10;
case Blue:
return 15;
case Green:
return 20;
}
return 0;
}
This works well and good but I was wondering if I could simplify things by using the enum itself to store the underlying values. For example, could I just define the enum as follows:
public enum ColorEnum { Red = 5, White = 10, Blue = 15, Green = 20 };
Then converting the enum to it's underlying value would be as simple as casting it to an int. The above function simplifies to the following:
public int colorToValue(ColorEnum color)
{
return (int)color;
}
Of course, the values for each enum entry would have to be an int as required by the enum definition.
Thanks!
Yes that is entirely valid and will work fine. Enums cast cleanly to/from their underlying type, and it is very common for them to have prescribed values rather than just 1,2,3...
The only thing to watch, though, is that the reverse is true too. So this works fine:
ColorEnum evil = (ColorEnum)(-53); // why not...
Your original colorToValue(evil) code would return 0 for this; your new code will return -53. Personally I might have thrown an ArgumentOutOfRangeException.
There is also an Enum.IsDefined method, but that involves boxing the value. But if you do want to check the input is an expected value, at least you can simplify:
public int colorToValue(ColorEnum color)
{
switch (color)
{
case Red:
case White:
case Blue:
case Green:
return (int)color;
default:
return 0; // or throw, whatever
}
}
I have an enum class called Gender, and I have values in this like:
public enum GENDER
{
MALE = 1,
FEMALE = 2,
OTHERS = 3,
}
And in my business object I just created a property for this, like:
public GENDER Gender
{
get
{
return gender;
}
set
{
gender = value;
}
}
In my database it's in type integer. For this I tried to assign the Gender value in the add function by its name Gender. But it's showing an error. Is it possible to cast the enum to integer so that it'll get the value automatically.
How can I fix this?
(int)Gender will do it. To cast a specific value instead of the property, you'll do something like (int)GENDER.MALE;
Enums by default "inherit" from int (they are stored in int by default unless you choose another integral type), so you can simply cast to and from int without any trouble:
int i = (int)GENDER.MALE;
GENDER g = (GENDER)2;
Note that implicit casting is not supported. Casting must be explicit.
Beware that the cast doesn't do any checks of the range, so you can cast an int that doesn't have a GENDER value into a GENDER variable without error:
GENDER g = (GENDER)26;
If (int)Gender is not enough to fix your cast issue, try to add int.Parse(var, int) in your code. It might be helpful...
You should be able to use a cast to convert between an integer and an enum value.
int n = (int)GENDER.MALE;
GENDER g = (GENDER)1;
If you're dealing with a string that you are reading from a database column (or any string for that matter) you can do the following:
GENDER g = (GENDER) Enum.Parse(typeof(GENDER), "MALE");
Note that Enum.Parse returns an object, so you have to cast it to your enum type first.
If you want to set the database value to gender property, do this:
yourintdatabasefiled = (int)GENDER.yourproperty
The following examples should suffice:
int val = (int)Gender.Male;
int val2 = (int)_gender;
There are also System.Enum methods to help you discover and manipulate enum values like:
Console.WriteLine("The values of the Gender Enum are: ");
foreach (int i in Enum.GetValues(typeof(Gender)))
{
Console.WriteLine(i);
}
The previous answers is right on it. Gender is now a type, just like int, so you can cast accordingly - both ways, too:
(int)Gender = . . .
/* Or */
(Gender)int = . . .
so, for
int i = (int)GENDER.male;
i would equal 1.
And the same for
Gender = GENDER.male;
i = (int)Gender;
i would also be 1.
Given this code:
public enum Enum1
{
ONE,
TWO
}
public enum Enum2
{
A,
B
}
This code returns ONE, TWO:
foreach (Enum1 e in Enum.GetValues(typeof(Enum1)))
{
Console.WriteLine(e);
}
But this code, instead of failing (because Enum2 e is used with typeof(Enum1)), returns A, B:
foreach (Enum2 e in Enum.GetValues(typeof(Enum1)))
{
Console.WriteLine(e);
}
Why is that?
Because under the covers Enums are just ints - the second returns the values of Enum1, but really those values are just 0 and 1. When you cast those values to the type Enum2 these are still valid and correspond to the values "A" and "B".
Because the values of your enums are implicitly integers:
public enum Enum1
{
ONE = 0,
TWO = 1
}
public enum Enum2
{
A = 0,
B = 1
}
The values of Enum1 are being implicitly converted to integers and then to values of Enum2. If you redefined Enum1 as follows...
public enum Enum1
{
ONE = 0,
TWO = 1,
THREE = 2,
}
...then it would fail not return "A, B", because there is no value in Enum2 for the integer value 2
When you use Enum.GetValues() it returns the underlying values. When you use foreach(Type...) it does a cast to the enum type. So, while they may not be the same Enum, they have the same underlying values which have no problem casting.
What is happening in roughly equivalent to this
int value = Enum.GetValues(typeof(Enum2))[1]; // this isn't valid code, it's more simplified
Enum1 casted = (Enum1)value;
Enum.GetValues(typeof(Enum1)) return {0,1} and foreach will enumerate in this range
There is an implicit cast here from Enum1 -> int and int -> Enum2.
I would guess someone like Jon Skeet could come in here and completely explain what is happening better than I am, but this code:
foreach (Enum2 e in Enum.GetValues(typeof(Enum1)))
{
Console.WriteLine(e);
}
...is seeing all of your Enum1 values as Enum2 types.
Since the enum data type is like the int data type, your numeric values from Enum1 are being used to index Enum2.
The reason for this is that enums are implicitly castable to System.Int (assuming they are int enums, which they are by default).
Your second foreach is then explicitly casting the results of Enum.GetValues(typeof(Enum1)) to Enum2.