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)
Related
For example, I have declared the following enum in C#.
C# code:
public enum LobMaster :int
{
RetailBroking = 1,
HNI = 2,
TechnologyInfrastructure = 3,
}
cshtml code:
#int code = 2
#if (LobMaster.RetailBroking == code)
{
}
If I try to compare int enum with integer value it gives me following error message.
operator '==' cannot be applied to types 'LobMaster' and 'int'
While my enum
LobMaster
is already an int type.
But when I cast the enum to int and then compare with int value it works fine.
So my question is why I need to cast enum to int as enum is already an int.
The main purpose of Enums is to remove "magic numbers", so you should ask yourself - why do you want to use those magic numbers?
Much better comparison would be:
Session["Lob_code"] is LobMaster && LobMaster.MassAffluent == (LobMaster)Session["Lob_code"]
This way you are avoiding those magic numbers and your code just provides all the context.
#if ((int) LobMaster.MassAffluent == Convert.ToInt32(Session["Lob_code"])) { }
you should be able to cast the left hand value and then do the conoarison
This question already has answers here:
How do I cast int to enum in C#?
(32 answers)
Closed 6 years ago.
If I have this code
//Spice Enums
enum SpiceLevels {None = 0 , Mild = 1, Moderate = 2, Ferocious = 3};
Which states the Enum Names + Their Number, how can I call an enum from a variable, say if a variable was 3, how do I get it to call and display Ferocious?
Just cast the integer to the enum:
SpiceLevels level = (SpiceLevels) 3;
and of course the other way around also works:
int number = (int) SpiceLevels.Ferocious;
See also MSDN:
Every enumeration type has an underlying type, which can be any integral type except char. The default underlying type of enumeration elements is int.
...
However, an explicit cast is necessary to convert from enum type to an integral type
enum SpiceLevels { None = 0, Mild = 1, Moderate = 2, Ferocious = 3 };
static void Main(string[] args)
{
int x = 3;
Console.WriteLine((SpiceLevels)x);
Console.ReadKey();
}
Enums inherit from Int32 by default so each item is assigned a numeric value, starting from zero (unless you specify the values yourself, as you have done).
Therefore, getting the enum is just a case of casting the int value to your enum...
int myValue = 3;
SpiceLevels level = (SpiceLevels)myValue;
WriteLine(level); // writes "Ferocious"
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.
I'm working with pulling a stream of bytes off of a medical device, and have run into a really annoying data structure. Basically, I am getting back a 2-byte chunk where each bit represents a boolean value. This structure appears frequently enough in the byte stream to develop a struct/class around it, but in each instance, the bits mean completely different things.
So first I set up a bunch of Enums to represent all the different definitions the bit structure could have. (Note that not every bit is used in every definition. Sometimes there are breaks in between the important bits.)
EDIT: Removed all names that looked like 'flag.' I'm not using the [Flags] attribute, and this seems to be a point of contention/confusion. The enum values are simply mapped to the indices in my BitArray.
public enum RecordInfo { AM_TEST = 0, PM_TEST, TEST_VALIDITY };
public enum RecordAlerts { ALERT1 = 0, ALERT2, ALERT3, ALERT4, VALIDATED = 15 };
Then created this container to hold the actual bits:
public struct TwoBytes<TEnum> where TEnum : struct, IConvertible
{
private BitArray _bits = new BitArray(2);
}
This seems to work as I need, until I want to index my structure based on an Enum name. So say I have a TwoByte struct called Alerts, and this contains some bit values. If I want to get a specific flag like this:
bool alert3Set = Alerts[RecordAlerts.ALERT3]
I end up with a truly heinous index function. This is what I have in place now:
public bool this[TEnum name]
{
get
{
int index = Enum.GetValues(typeof(TEnum)).Cast<TEnum>().ToList().Where(x => x.Equals(name)).Cast<int>().First();
return _bits[index];
}
}
Now it works, crazily enough. But that LINQ chains looks positively atrocious, and it takes a while to decipher what it's actually doing.
Is there a cleaner, more efficient way of converting a generic Enum 'name' to its integer value? Or would I be better suited to use a Dictionary (or some other object) to represent the bit structure definitions?
As long as every TEnum you'd use derives from int (the default), and not from another number type, this will work:
public bool this[TEnum name]
{
get
{
int index = (int)(object)name;
return _bits[index];
}
}
If you want to support enums derived from smaller types (and enums that only use values within the range supported by int), I'd use:
public bool this[TEnum name]
{
get
{
int index = Convert.ToInt32(name);
return _bits[index];
}
}
(fully supporting enums derived from types that can't implicitly be converted to int, like uint, long, and ulong, gets more complicated, because BitArray's indexer uses an int)
I think a bit of OOP would make your life easier. You can introduces classes that represent the data you receive, and has meaningful property names. Each class could accept your BitArray into constructor and parse it into properties.
Further in your program you could use these classes instead of fiddling with bits.
As FrankPI suggested in the comments, why not use an enum whose values really represent each bit, rather than using an intermediate BitArray?
[Flags]
public enum RecordFlags { FLAG1 = 0x1, FLAG2 = 0x2, FLAG3 = 0x4, FLAG4 = 0x8, FLAG5 = 0x10, VALIDATED = 0x8000 };
var readFlags = (RecordFlags) ((bytes[0] << 8) | bytes[1]);
bool hasFlag2 = (readFlags & RecordFlags.Flag2) != 0;
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)