C# Overloading Enums To Store Values - c#

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

Related

Indexer that points to item in struct array don't work

I have a class called Surface, in this class i have an array of type struct Color.
public class Surface
{
private Color[,] pixels;
public Color this[int x, int y]
{
get { return pixels[y, x]; }
}
}
[StructLayout(LayoutKind.Explicit)]
public struct Color
{
[FieldOffset(0)]
public byte R;
public void Set(byte r)
{
R = r;
}
}
However when i try to access the color using the indexer it don't get updated.
mySurface[x, y].Set(255); // Will not work, i don't get an error but the color don't get updated.
How can i solve this problem?
How can i solve this problem?
Well you could avoid creating mutable structs and exposing public fields, to start with. That's where the problem is coming from. Your code is effectively:
Color tmp = mySurface[x, y]; // Take a copy from the array...
tmp.Set(255); // This only affects the copy
To change the array, you'll need to call the setter on the indexer instead. For example:
Color tmp = mySurface[x, y];
tmp.Set(255);
mySurface[x, y] = tmp;
Assuming you actually have several values in your struct, it would be simpler if you'd make your struct immutable but provide methods that returned new values, just like DateTime.AddDays etc. Then you could write code like:
mySurface[x, y] = mySurface[x, y].WithRed(255);
Options if you really want to avoid using a setter:
Use ref return from C# 7: redefine your indexer to return a ref Color; although then you can't have a setter.
Make Color a class instead of a struct
Use a reference type inside Color, so you don't need to change the bits in the Color value itself. (This is really nasty - I'm not suggesting that.)
Structs are value types, so if you get it from the array by calling pixels[y,x], you will actually create a copy of the struct to change the field on.
See also Unable to Modify struct Members

Switch Case Returns "A Constant Value is expected"

I searched around, everyone else who had this problem was using the .ToString method and I am not so I am at a loss.
On the last line I get a return of "A Constant Value is expected"
I know if I remove the part where I give the enum's values it works, but that kinda defeats the purpose of me using an Enum. Any suggestions about the best way to accomplish this?
public enum Colors
{
Blue = "0000FF",
Red = "FF0000",
Green= "00FF00"
}
private void colorstuff(Colors Color){
switch (Color ){
case Colors.Blue:
}
}
**EDIT So I have been made aware that ENUM's cannot have a STRING type. Can anyone suggest a method for making a SET of String Types? If I just declare
const Blue = "0000FF",
const Red = "FF0000",
const Green= "00FF00"
They are not attached to one another.
Enums are based on int data type, so you need to declare them like this:
Blue = 0x0000FF
Alternatively declare a class:
public static class MyColours
{
public const string Blue = "0000FF";
}
dear you can't define enum like this , because it's int type.
public enum Colors
{
Blue = 0000FF,
Red = FF0000,
Green= 00FF00
}

Switch statement: Not all code paths return a value

I have an enum defined as follows:
public enum CrystalTypeEnum { Red, White, Blue, Green };
and I have a static function that returns the string representation of a given enum value:
public static string toString(CrystalTypeEnum type)
{
switch (type)
{
case CrystalTypeEnum.Red:
return "Red";
case CrystalTypeEnum.White:
return "White";
case CrystalTypeEnum.Blue:
return "Blue";
case CrystalTypeEnum.Green:
return "Green";
}
}
When I compile my code I get the following error:
CrystalType.toString(CrystalType.CrystalTypeEnum): not all code paths return a value
Why am I getting this error when clearly my switch statement covers all four cases (Red, White, Blue, Green).
If there is no default: control is transferred to outside of the switch statement (for values not handled by a case). This means if you don't have a default: then you need a return statement after the switch that returns a value of the type defined by the return type of the method.
You need to specify a default section.
switch (type)
{
case CrystalTypeEnum.Red:
return "Red";
case CrystalTypeEnum.White:
return "White";
case CrystalTypeEnum.Blue:
return "Blue";
case CrystalTypeEnum.Green:
return "Green";
default:
//return what you need here
}
Do not forget to use this section in switch\case construction:
switch (type)
{
default:
throw new ArgumentException("Incorrect CrystalTypeEnum");
}
Why am I getting this error when clearly my switch statement covers all four cases (Red, White, Blue, Green).
Because there are five cases in total not four. You can cast an integer that is not one of these defined enum values to CrystalTypeEnum type and it is still valid.
CrystalType.toString((CrystalTypeEnum)(42));
So in a switch statement default is always required?
No, you can place the return statement after the whole switch clause or anything as long as "all code paths return a value".
I know that the answer posted by astander, may be what you are looking for, but there is an elegnt way to do this, which wont require any switch statements.
You can use Enum.GetName method to get the string representation of an enum value.
Please read here

C# Copying Enumeration from one object to another

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

Can I specify a default Color parameter in C# 4.0?

Here is an example function:
public void DrawSquare(int x, int y, Color boxColor = Color.Black)
{
//Code to draw the square goes here
}
The compiler keeps giving me the error: Default parameter value for 'boxColor'must be a compile-time constant
I have tried
Color.Black,
Color.FromKnownColor(KnownColor.Black), and
Color.FromArgb(0, 0, 0)
How do I make Color.Black be the default color? Also, I do not want to use a string Black to specify it (which I know would work). I want the Color.Black value.
Color.Black is a static, not a constant, so no, you cannot do this.
To use a default, you can make the parameter nullable (Color?), and if it is null, then set it to Black.
Do this:
void foo(... Color boxColor = default(Color))
{
if(object.Equals(boxColor, default(Color))) boxColor = Color.Black;
// ...
}
Quick aside: I like to use object.Equals static method because it's a consistent way to write an equality comparison. With reference types such as string, str.Equals("abc") can throw NRE, whereas string.Equals(str, "abc"[,StringComparison.___]) will not. Color is a value type and therefore will never be null, but it's better to be consistent in code style, especially at zero additional cost. Obviously this doesn't apply to primitives such as int and even DateTime, where == clearly states/communicates the mathematical equality comparison.
Or, with nullables (credit to Brian Ball's answer):
void foo(... Color? boxColor = null)
{
if(boxColor == null) boxColor = Color.Black;
// ...
}
What's wrong with keeping it simple?
public void DrawSquare(int x, int y)
{
DrawSquare(x,y,Color.Black);
}
public void DrawSquare(int x, int y, Color color)
{
// Do your thing.
}

Categories

Resources