After reading the recent question Operations between different enum types are allowed in another enum declaration but not elsewhere I've come up with this example:
enum Alpha : long
{
X,
}
enum Beta : ulong
{
X,
}
enum Gamma : long
{
X = Alpha.X | Beta.X, // problem?
}
enum Delta : ulong
{
X = Alpha.X | Beta.X, // no problem?
}
Result of compiling: Gamma
will not compile (CS0266: Cannot implicitly convert type 'ulong' to 'long'. An explicit conversion exists (are you missing a cast?)). Delta
compiles happily.
Is this not something not to be expected from the C# Language Specification?
(Note: If I change the member of Alpha
to be initialized to a negative constant, like -1L
, then neither Gamma
nor Delta
will compile.)
Yes, it's expected and it's not something enum-specific. You can simplify it to:
long a = 1L | 1UL; // Cannot implicitly convert type 'ulong' to 'long'. An explicit conversion exists (are you missing a cast?)
ulong b = 1L | 1UL;
The following quotes from the C# Language Specification describes why it happens.
6.1.9 Implicit constant expression conversions
An implicit constant expression conversion permits the following conversions:
· A constant-expression (§7.19) 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.
· A constant-expression of type long can be converted to type ulong, provided the value of the constant-expression is not negative.
6.1.2 Implicit numeric conversions
The implicit numeric conversions are:
· From long to float, double, or decimal.
· From ulong to float, double, or decimal.
In other words, Alpha.X
(if the underlying value is positive) can be (an actually is!) implicitly converted to ulong
. But the result of Alpha.X | Beta.X
is ulong
, which, according to the specs, cannot be implicitly converted to the long
.
But once you change the Alpha.X
to be initialized to a negative constant, like -1L
, then, according to the quote above, it can no longer be implicitly converted to ulong
and compilation will fail with a different error: Operator '|' cannot be applied to operands of type 'long' and 'ulong'