Enum to integer cast - c#

I have a problem with enum in c#
enum myenum {one, two, three} ;
Public myenum type;
type=2;
Why it doesn't work? How to cast enum to integer in such a way?

You have to explicitly cast integer to myenum:
type = (myenum) 2;
See this thread for more explanation: Cast int to enum in C#

There is no implicit conversion between an int and enum. There is however an explicit conversion
type = 2; // Error
type = (myenum)2; // Ok
The one exception to this rule is the literal 0. The literal 0 implicitly converts to any enum type
type = 0; // Ok

You can explicitly convert between the two, also ensure that you declare the enums with a specific value as the automatic index starts from zero.
enum myenum {one = 1, two = 2, three = 3} ;
private void GoEnum()
{
myenum x = (myenum)1;
Console.WriteLine(x);
Console.WriteLine((int)x);
}

The entire purpose of enums is to avoid "magic numbers". Their purpose is to avoid code just like that in which the reader needs to just "know" that 2 represents myenum.two. Behind the scenes it is just an integer (or some other integral type) but the language works to hide that fact from you.
It does allow you to convert an integer into it's enumeration representation, and vice versa, because there are times where this is simply necessary, but because it should be avoided wherever possible the language forces you to explicitly cast the integer (type = (myenum) 2;), rather than implicitly converting it for you, so that your intentions are made very clear in code.

Unless specified, an enum cannot be converted to an integer without a cast (which is unsafe). You have to assign integer values to each option in the enum.
Example:
enum MyEnum {
One,
Two,
Three
};
Would become:
enum MyEnum {
One = 1,
Two = 2,
Three = 3
};
An enum takes up the size of an integer (4 bytes). This allows a cast to int, but like I have said it is better practise to assign values to enum options. If you wanted to change the value that MyEnum extends, do this:
enum MyEnum : long /* or short, ushort, ulong, uint, sbyte, byte etc */ {
One = 1L,
Two = 2L,
Three = 3L
};
Note that the only types that can be used are:
byte, sbyte, short, ushort, int, uint, long or ulong
This does not include anything like System.Integer or System.Byte.

Related

sbyte and if operator

Why the first statement is allowed but not the second in the below sample code?
sbyte test1 = true ? 1 : -1; // Allowed
sbyte test2 = "a".Equals("b") ? 1 : -1; // Not allowed
I checked that all .Equals(..) overloads for string return a bool.
The first statement includes a constant expression that can be evaluated at a compile-time. It's equivalent to this:
sbyte test1 = 1;
Technically, this is an assignment of an int literal (1) to an sbyte variable. But the compiler is smart enough to figure out that the value is small enough to fit into an sbyte range and allows an implicit conversion, i.e. you don't need to cast it to int.
The second statement includes a method call and those are only evaluated at runtime. In other words, the compiler isn't smart enough to simplify an expression. The only thing it knows is that this impression returns an unknown int value and those should be converted explicitly. For example, like this:
sbyte test2 = (sbyte) ("a".Equals("b") ? 1 : -1);
All of this is explained in the C# specification. See, Implicit constant expression conversions:
A constant_expression (Constant expressions) of type int can be converted to type sbyte, byte, short, ushort, uint, or ulong, provided the value of the constant_expression is within the range of the destination type.

Do I need to cast enums to their numerical counterpart? [duplicate]

This question already has answers here:
Byte enum comparison in C#
(3 answers)
Closed 8 years ago.
I have set up a enum like this:
public enum ServerCommands:byte {
New = 0,
Join = 1,
}
And I want to use it like this:
byte command = buffer[0];
if (command == ServerCommands.Join) // Error: Operator == cannot be operands of type 'byte' and 'ServerCommands'.
Why is this not possible to do and how can I make it work? They are both of type byte.
You still need to cast from byte to ServerCommands! This is not done automatically. Assinging numbers to enum values is just for clarity when casting enum to int or other permitted numeric types.
Assigning numeric values to enum values does not change their type to the numeric type! You can cast any enum value to an int, as all enums (if not declared otherwise) can be cast to int, the first enum value having int value 0.
public enum MyEnum
{
First,
Second
}
is equal to
public enum MyEnum : int
{
First = 0,
Second
}
The feature of numbering enum values is required if the number is not linear, as in:
public enum ErrorCodes: int
{
Success = 0,
FileNotFound = 1,
MissingRights = 5,
WhatTheHeck = 18
}
You better state conversions explicitly:
if (command == (byte) ServerCommands.Join)
or even better:
if ((ServerCommands) command == ServerCommands.Join) //always convert to the more restrictive type.
This is a precaution to prevent one from comparing values without knowing that the objects are from a different type.
Equality means that both objects have the same type. This is not the case. ServerCommands extend from byte. Thus a byte is not per se a valid ServerCommands object...
Furthermore the : byte is more used as an explicit encoding. Having the same binary encoding does not imply two objects are the same. For instance 14.25f and 0x41640000 are binary the same...
You probably need to cast your enum:
if (command == (byte)ServerCommands.Join)

Cast number to type?

How do you go about casting numbers to specific data types?
Example:
253 is 32-bit signed integer
253L is 64-bit signed integer
253D is Double precision float
As you can see you can cast directly to Long and Double, but there are certain problems I have here. I cannot cast to byte, single, 16bit, unsigned...
It becomes a problem when I have to input data into many different functions with arguments of varying data types:
Method1( byte Value );
Method2( sbyte Value );
Method3( ushort Value );
//Etc.
Using int.Parse(string) or Convert.ToInt32 will do the trick.
Or you could try casting the value expicitly like that:
int age = 53;
Method1((byte) age);
Try using the Convert class:
http://msdn.microsoft.com/en-us/library/System.Convert_methods(v=vs.110).aspx
e.g.
int myInt = Convert.ToInt32(anything);

Enum of long values in C#

Why does this declaration,
public enum ECountry : long
{
None,
Canada,
UnitedStates
}
require a cast for any of its values?
long ID = ECountry.Canada;
// Error Cannot implicitly convert type 'ECountry' to 'long'.
// An explicit conversion exists (are you missing a cast?)
And is there a way to get a long value directly from the enum, besides casting?
This would not work either, for example:
public enum ECountry : long
{
None = 0L,
Canada = 1L,
UnitedStates=2L
}
The issue is not that the underlying type is still int. It's long, and you can assign long values to the members. However, you can never just assign an enum value to an integral type without a cast. This should work:
public enum ECountry : long
{
None,
Canada,
UnitedStates = (long)int.MaxValue + 1;
}
// val will be equal to the *long* value int.MaxValue + 1
long val = (long)ECountry.UnitedStates;
The default underlying type of enum is int. An enum can be any integral type except char.
If you want it to be long, you can do something like this:
// Using long enumerators
using System;
public class EnumTest
{
enum Range :long {Max = 2147483648L, Min = 255L};
static void Main()
{
long x = (long)Range.Max;
long y = (long)Range.Min;
Console.WriteLine("Max = {0}", x);
Console.WriteLine("Min = {0}", y);
}
}
The cast is what is important here. And as #dlev says, the purpose of using long in an enum is to support a large number of flags (more than 32 since 2^32 is 4294967296 and a long can hold more than 2^32).
You must cast an enum to get a value from it or it will remain an enum type.
From MSDN:
In this example, the base-type option is used to declare an enum whose members are of the type long. Notice that even though the underlying type of the enumeration is long, the enumeration members must still be explicitly converted to type long using a cast.
// keyword_enum2.cs
// Using long enumerators
using System;
public class EnumTest
{
enum Range :long {Max = 2147483648L, Min = 255L};
static void Main()
{
long x = (long)Range.Max;
long y = (long)Range.Min;
Console.WriteLine("Max = {0}", x);
Console.WriteLine("Min = {0}", y);
}
}
Output
Max = 2147483648 Min = 255
AFAIK, you have got to cast.
The MSDN article says:
"However, an explicit cast is needed to convert from enum type to an integral type" (either int or long)
You can check it out:
Enumeration types (C# reference)

Why don't I get InvalidCastException when casting enum to integer fails?

public enum Animal
{
Dog = 1,
Cat = 2,
Cow = 3
}
int animalID = 4;
if ((Animal)animalID == Animal.Dog) // does not throw exception
animalID can't be casted to Animal.
Why don't I get InvalidCastException when casting enum to integer fails?
Because it's not an invalid cast.
The value you are casting is out of range for the enum (in this case) but it's not invalid.
As the approved types for an enum are byte, sbyte, short, ushort, int, uint, long, or ulong a cast from integer to enum is perfectly legal.
Source - MSDN
This is an intended behaviour and can be pretty useful. Consider enums defined with the [Flag] attribute.
btw, this is a dupe of
Casting an out-of-range number to an enum in C# does not produce an exception
more answers may be in there :)

Categories

Resources