C# Int, Int32 and Enums

C# int, Int32 and enums

The underlying type is indeed the same, but the compiler depends on the type to be as the exact alias. This is a compilation error based on parsing. I took a look at C# grammar specification and the underlying types defined there as tokens based on the alias (e.g. 'int', 'unit'... etc.). The parser expects specific strings from the integral-types grammar rule.

The error is a parsing error even though both enum Enum : int means the same as enum Enum : Int32.

I don't know the reason for forcing this limit to parsing step, but I can try guessing: Since Int32 is not a keyword it might refer to something other the actual int struct. If the parser has to know the type in order to build different AST for each base type then it cannot depend on token which is not a keyword.

Even though the C# specification defines the int keyword as explicit alias System.Int32, it's still a problem to get this information about the explicit type (Int32) during parsing step since it requires a lot of context information which cannot be inferred at this step.

enum members of Int32 type

From a Microsoft bug report here:

Symptom

If you use System.Int16/Int32/Int64 instead of Short/Int/Long to declare Enum, it will get compilation error.

Root Cause

It's by design. Using value type alias is required exactly in Enum declaration.

It is "by design".

  1. The syntax is correct. C# specification explicitly states that the enum's underlying type must be byte, sbyte, short, ushort, int, uint, long or ulong.

  2. Although the underlying type of “Short” and "System.Int16" are one and the same, they are not as identical as you assume. The System.Int16 is a type, and the Short is a type keyword.

  3. ValueType is sealed. You cannot inherit from any class that derives from System.ValueType.

  4. But, it allows you to use the keyword to control. The intent is to prevent your using names of any types that derive from System.ValueType when declaring other types. The original intent is to provide a tightly controlled mechanism that allows you to declare types that inherit from System.ValueType.
    However, MSDN says "The C# type keywords and their aliases are interchangeable", which often let customers feel confused/inexplicable. They think it’s a compiler or grammar bug.

Business Impact / Customer Experience

Since the “Short” and "System.Int16" are the same one underlying type and can be interchangeable, many customers feel confused/inexplicable why it cannot be interchangeable in Enum declaration. They think it’s a compiler or grammar bug.
The Voice of customers:
This sounds like a small compiler bug (small becuase its easy to workaround).
Here is what MSDN says "The C# type keywords and their aliases are interchangeable."
In my view this is a real but tiny, compiler (or perhaps grammar) bug.
The fact that the compiler lets you use "short" here and not "System.Int16" is a quirk of the compiler (perhaps not a bug, but a quirk).

Expression.Call, Int32 and Enum

Wouldn't this do the trick?

MemberExpression member = Expression.Convert(
Expression.Property(pe, item.Member), typeof(int);
ConstantExpression value = Expression.Constant((int)item.Value);

Why should I make the underlying type of an Enum Int32 instead of byte?

Have a look on MSDN for the reason.

Here is an excerpt:

An enumeration is a value type that defines a set of related named
constants. By default, the System.Int32 data type is used to store the
constant value. Even though you can change this underlying type, it is
not necessary or recommended for most scenarios. Note that no
significant performance gain is achieved by using a data type that is
smaller than Int32. If you cannot use the default data type, you
should use one of the Common Language System (CLS)-compliant integral
types, Byte, Int16, Int32, or Int64 to make sure that all values of
the enumeration can be represented in CLS-compliant programming
languages.

Why does 'Int32 value__' show up as enum member?

Well, not always. Try to change the definition of the enum to public enum Colors : byte. The value member will be Byte value__ then.

You will see that the first member of an enum is the actual backing storage for the enum value.

How int is the backing type for enum

Int32 is just the default underlying type for enum, however this is changeable. You can change this by specifying a different datatype e.g.

enum ExampleEnum : byte
{
Value1,
Value2,
Value3
};

Here is what Microsoft says regarding the enum:

Every enumeration type has an underlying type, which can be any integral type except char.

The default underlying type of enumeration elements is int.

To declare an enum of another integral type, such as byte, use a colon after the identifier followed by the type,

...

The approved types for an enum are byte, sbyte, short, ushort, int, uint, long, or ulong.

^ Source MSDN: enum (C# Reference)

Enum to int, why use type cast to int rather than Convert.ToInt32(Enum)?

By default, enums inherit from int, i.e. behind the scenes it is:

enum Foo : int
{
A,
B
}

In C#, there is no difference between Int32 and int. So using Convert.ToInt32(Foo.A) is a bit redundant, since performing (int)Foo.A will suffice. Personally, (int)Foo.A also reads much better. Note, you would only really have to watch this in situations where you defined your enum like so:

enum Foo : long
{
A,
B
}

Get int value from enum in C#

Just cast the enum, e.g.

int something = (int) Question.Role;

The above will work for the vast majority of enums you see in the wild, as the default underlying type for an enum is int.

However, as cecilphillip points out, enums can have different underlying types.
If an enum is declared as a uint, long, or ulong, it should be cast to the type of the enum; e.g. for

enum StarsInMilkyWay:long {Sun = 1, V645Centauri = 2 .. Wolf424B = 2147483649};

you should use

long something = (long)StarsInMilkyWay.Wolf424B;

How do I cast int to enum in C#?

From an int:

YourEnum foo = (YourEnum)yourInt;

From a string:

YourEnum foo = (YourEnum) Enum.Parse(typeof(YourEnum), yourString);

// The foo.ToString().Contains(",") check is necessary for
// enumerations marked with a [Flags] attribute.
if (!Enum.IsDefined(typeof(YourEnum), foo) && !foo.ToString().Contains(","))
{
throw new InvalidOperationException(
$"{yourString} is not an underlying value of the YourEnum enumeration."
);
}

From a number:

YourEnum foo = (YourEnum)Enum.ToObject(typeof(YourEnum), yourInt);

C# - Can you call an Enum by the number value?

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



Related Topics



Leave a reply



Submit