By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
435,269 Members | 1,561 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 435,269 IT Pros & Developers. It's quick & easy.

Why do enum values req explicit conversions

P: n/a
If a class inherits from another class, say Form inherits from control, then
I can assign the Form to a variable of type Control without needing an
explicit conversion, eg

Form1 f = new Form1();
Control c = f;

An enum value inherits from int but it doesn't get implicitly converted:

HorizontalAlignment h = HorizontalAlignment.Center;
int i = h;

Any reason?

Thanks,
Michael
Nov 17 '05 #1
Share this Question
Share on Google+
31 Replies


P: n/a
The difference is that Form is a subclass of Control. A basic rule of
inheritance (what is that guy's name again?) is that the subclass can always
be substituted for the superclass.

The problem is that an enum is not a subclass of an int (or long or sbyte or
uint, etc..). At run time, enums are treated as boxed types of the
underlying enum type. That is why you must unbox it to get the integer
value.

HTH

Dale Preston
MCAD, MCDBA, MCSE
"Michael C" <mc*****@NOSPAMoptushome.com.au> wrote in message
news:uO**************@TK2MSFTNGP14.phx.gbl...
If a class inherits from another class, say Form inherits from control, then I can assign the Form to a variable of type Control without needing an
explicit conversion, eg

Form1 f = new Form1();
Control c = f;

An enum value inherits from int but it doesn't get implicitly converted:

HorizontalAlignment h = HorizontalAlignment.Center;
int i = h;

Any reason?

Thanks,
Michael

Nov 17 '05 #2

P: n/a
enums are boxed at run time? That doesn't seem right to me. (But I
could be wrong. :)

I was going to say that it's more a question of self-documenting code.
One really ought to treat an enumeration as a self-contained type, even
though it is, underneath it all, just an int (or whatever). So, if you
want to start manipulating it as if it were a number, you have to cast
in order to raise a flag to the reader: "I'm doing something unusual
here! Pay attention!"

Other than that I can't see any reason.

Nov 17 '05 #3

P: n/a
From the C# specification:

At run-time, a value of type System.Enum can be null or a reference to a
boxed value of any enum type.

Dale

"Bruce Wood" <br*******@canada.com> wrote in message
news:11**********************@z14g2000cwz.googlegr oups.com...
enums are boxed at run time? That doesn't seem right to me. (But I
could be wrong. :)

I was going to say that it's more a question of self-documenting code.
One really ought to treat an enumeration as a self-contained type, even
though it is, underneath it all, just an int (or whatever). So, if you
want to start manipulating it as if it were a number, you have to cast
in order to raise a flag to the reader: "I'm doing something unusual
here! Pay attention!"

Other than that I can't see any reason.

Nov 17 '05 #4

P: n/a
"Dale Preston" <da******@nospam.nospam> wrote in message
news:uV**************@TK2MSFTNGP14.phx.gbl...
From the C# specification:

At run-time, a value of type System.Enum can be null or a reference to a
boxed value of any enum type.


Are you confusing the enum itself with the elements in it? (It's confusing
me a little). The actual enum inherits from enum but the elements don't as
far as I can tell. On the other hand it's possible to set one of the
elements to a variable of type System.Enum implicitly.

Michael
Nov 17 '05 #5

P: n/a
The enum elements inherit from System.Enum.
"Michael C" <mc*****@NOSPAMoptushome.com.au> wrote in message
news:#G**************@TK2MSFTNGP14.phx.gbl...
"Dale Preston" <da******@nospam.nospam> wrote in message
news:uV**************@TK2MSFTNGP14.phx.gbl...
From the C# specification:

At run-time, a value of type System.Enum can be null or a reference to a
boxed value of any enum type.


Are you confusing the enum itself with the elements in it? (It's confusing
me a little). The actual enum inherits from enum but the elements don't as
far as I can tell. On the other hand it's possible to set one of the
elements to a variable of type System.Enum implicitly.

Michael

Nov 17 '05 #6

P: n/a
Another thing to keep in mind, enums can use, as the underlying type (not
the base type, only the numeric representation type) an integer, long, byte,
uint, short, ushort, etc

You can't expect to implicitly convert to an int.

Dale

"Michael C" <mc*****@NOSPAMoptushome.com.au> wrote in message
news:#G**************@TK2MSFTNGP14.phx.gbl...
"Dale Preston" <da******@nospam.nospam> wrote in message
news:uV**************@TK2MSFTNGP14.phx.gbl...
From the C# specification:

At run-time, a value of type System.Enum can be null or a reference to a
boxed value of any enum type.


Are you confusing the enum itself with the elements in it? (It's confusing
me a little). The actual enum inherits from enum but the elements don't as
far as I can tell. On the other hand it's possible to set one of the
elements to a variable of type System.Enum implicitly.

Michael

Nov 17 '05 #7

P: n/a
"Dale Preston" <da******@nospam.nospam> wrote in message
news:OM**************@tk2msftngp13.phx.gbl...
The enum elements inherit from System.Enum.
I suspected this might be the case even though the object browser says it's
not. So it is inherited from Enum and NOT from int? It can be explicitly
converted to int but it's not actually an int? It's a bit misleading the
syntax then:

Public Enum ABC : int
{
....
}
Another thing to keep in mind, enums can use, as the underlying type (not
the base type, only the numeric representation type) an integer, long,
byte,
uint, short, ushort, etc

You can't expect to implicitly convert to an int.


There's no reason it shouldn't be possible

Michael
Nov 17 '05 #8

P: n/a

"Michael C" <mc*****@NOSPAMoptushome.com.au> wrote in message
news:%2****************@TK2MSFTNGP09.phx.gbl...
"Dale Preston" <da******@nospam.nospam> wrote in message
news:OM**************@tk2msftngp13.phx.gbl...
The enum elements inherit from System.Enum.
I suspected this might be the case even though the object browser says
it's not. So it is inherited from Enum and NOT from int? It can be
explicitly converted to int but it's not actually an int? It's a bit
misleading the syntax then:

Public Enum ABC : int
{
...
}


It is, but what other way is there that doesn't cause extra complexity?

You can't expect to implicitly convert to an int.


There's no reason it shouldn't be possible


Explicit conversion is required for consistency(Technically you are losing
information, however litttle and easily regained) and to avoid making silly
mistakes.

0 has an implicit conversion to any enum, all other literals and enums must
be converted.
Nov 17 '05 #9

P: n/a

"Dale Preston" <da******@nospam.nospam> wrote in message
news:uV**************@TK2MSFTNGP14.phx.gbl...
From the C# specification:

At run-time, a value of type System.Enum can be null or a reference to a
boxed value of any enum type.
That is because System.Enum *IS* a reference type, while derivatives are
value types. You will see a similar dichotomy in System.ValueType. A value
of any given enum is just a value on the stack(literally the base type as I
don't believe enums have any other fields), but when put into a System.Enum
variable they must be boxed.

Dale

"Bruce Wood" <br*******@canada.com> wrote in message
news:11**********************@z14g2000cwz.googlegr oups.com...
enums are boxed at run time? That doesn't seem right to me. (But I
could be wrong. :)

I was going to say that it's more a question of self-documenting code.
One really ought to treat an enumeration as a self-contained type, even
though it is, underneath it all, just an int (or whatever). So, if you
want to start manipulating it as if it were a number, you have to cast
in order to raise a flag to the reader: "I'm doing something unusual
here! Pay attention!"

Other than that I can't see any reason.


Nov 17 '05 #10

P: n/a
"Daniel O'Connell [C# MVP]" <onyxkirx@--NOSPAM--comcast.net> wrote in
message news:OP**************@TK2MSFTNGP10.phx.gbl...
It is, but what other way is there that doesn't cause extra complexity?
I guess it makes sense if you think of it as a parameter to specify how an
object is defined, as opposed to what it inherits from.
Explicit conversion is required for consistency(Technically you are losing
information, however litttle and easily regained) and to avoid making
silly mistakes.


That makes sense.

Michael
Nov 17 '05 #11

P: n/a
Yes, this is true. Enumerated values are not boxed unless you store
them in a variable declared as System.Enum. I created the following
code as a test:

public class ConsoleClass
{
public ConsoleClass()
{ }

public enum Enumeration
{
Nothing,
FirstValue,
SecondValue,
ThirdValue
}

[STAThread]
public static void Main(string[] argc)
{
Enumeration a = Enumeration.Nothing;
Enumeration b = Enumeration.SecondValue;
Enumeration c = a | b;
Enum d = a;
}
}

The resulting intermediate language code looks like this:

..method public hidebysig static void Main(string[] argc) cil managed
{
.entrypoint
.custom instance void [mscorlib]System.STAThreadAttribute::.ctor() =
( 01 00 00 00 )
// Code size 16 (0x10)
.maxstack 2
.locals init ([0] valuetype
ConsoleApplication1.ConsoleClass/Enumeration a,
[1] valuetype ConsoleApplication1.ConsoleClass/Enumeration
b,
[2] valuetype ConsoleApplication1.ConsoleClass/Enumeration
c,
[3] class [mscorlib]System.Enum d)
IL_0000: ldc.i4.0
IL_0001: stloc.0
IL_0002: ldc.i4.2
IL_0003: stloc.1
IL_0004: ldloc.0
IL_0005: ldloc.1
IL_0006: or
IL_0007: stloc.2
IL_0008: ldloc.0
IL_0009: box ConsoleApplication1.ConsoleClass/Enumeration
IL_000e: stloc.3
IL_000f: ret
} // end of method ConsoleClass::Main

Notice that there is only one box operation: when I assign a, which is
declared as an Enumeration, to d, which is declared as System.Enum.
It's just like assigning an int to a System.Object. Even though int
inherits from System.Object, ints are not held as boxed values unless
you actually assign one to a variable of type System.Object.

Nov 17 '05 #12

P: n/a
Bruce Wood <br*******@canada.com> wrote:

<code>
Notice that there is only one box operation: when I assign a, which is
declared as an Enumeration, to d, which is declared as System.Enum.
It's just like assigning an int to a System.Object. Even though int
inherits from System.Object, ints are not held as boxed values unless
you actually assign one to a variable of type System.Object.


It makes a lot more sense - while at the same time becoming more
confusing - when you read the CIL spec.

The value type "System.Int32" itself *doesn't* inherit from
System.Object (directly or indirectly). However, there is another type,
also called "System.Int32" which *does* inherit from System.Object -
and that's the boxed version.

Basically, every value type has a reference type of the same name which
is the boxed form. That's the one which actually derives from
System.ValueType or System.Enum.

There's no way that I know of of getting references to two different
Type objects, one for the boxed version and one for the value type
version though...

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 17 '05 #13

P: n/a
This is from the C# specification in the Visual Studio documentation:

"The type System.Enum is the abstract base class of all enum types (this is
distinct and different from the underlying type of the enum type), and the
members inherited from System.Enum are available in any enum type."

If enums don't inherit from System.Enum, then what exactly does "abstract
base class" mean in that context? Note that the statement says that the
base class is "distinct and different" from the underlying type of the enum.
The underlying type of the enum is returned by the TypeCode returned from
the instance GetTypeCode method. If the enum does not inherit from
System.Enum, then how is it that the instance enum gets the GetTypeCode
method? It certainly doesn't get it from the underlying type. Int32
doesn't have a GetTypeCode method. And Int32 is sealed and cannot be
inherited from.

From the .Net Framework documentation of the System.Enum class:

"Class Enum is derived from class ValueType; that is, Enum is itself a
reference type, not a value type."

Because Enum is a reference type, it must be unboxed to get the integral
underlying type. Again, from the C# specification:

"an unboxing conversion (Section 4.3.2) exists from System.Enum to any enum
type."

While many of the guesses about why you have to explicitly cast to get the
integer make logical sense and might be good reasons for the requirement,
they are not supported either by the language specification, by the
framework documentation, or by the object-oriented principals of
inheritance.

Dale

"Daniel Jin" <Da*******@discussions.microsoft.com> wrote in message
news:0B**********************************@microsof t.com...
that's where it actually gets a little screwy.

enums don't exactly "inherit" from System.Enum (a reference type) like how
normal class inheritance works. just like structs don't literally "inherit" from System.ValueType (another reference type). enums are not boxed, just
like value types are not boxed. that'd be a huge performance killer if
otherwise.

back to op, why require the cast? my guess is for type safety. so enum
values are not accidentally passed to a method expecting integer parameter.
"Dale Preston" wrote:
The enum elements inherit from System.Enum.
"Michael C" <mc*****@NOSPAMoptushome.com.au> wrote in message
news:#G**************@TK2MSFTNGP14.phx.gbl...
"Dale Preston" <da******@nospam.nospam> wrote in message
news:uV**************@TK2MSFTNGP14.phx.gbl...
> From the C# specification:
>
> At run-time, a value of type System.Enum can be null or a reference to a > boxed value of any enum type.

Are you confusing the enum itself with the elements in it? (It's confusing me a little). The actual enum inherits from enum but the elements don't as far as I can tell. On the other hand it's possible to set one of the
elements to a variable of type System.Enum implicitly.

Michael


Nov 17 '05 #14

P: n/a
"Daniel Jin" <Da*******@discussions.microsoft.com> wrote in message
news:0B**********************************@microsof t.com...
back to op, why require the cast? my guess is for type safety. so enum
values are not accidentally passed to a method expecting integer
parameter.


Originally I was trying to replace this code with a function

if ((SomeEnumValue & SomeEnum.SomeFlag) != 0)
{
}

with a function, something like

if(EnumContainsFlag(SomeEnumValue, SomeEnum.SomeFlag))

But I can't pass them in as System.Enum becuase I can't convert them to int
and I can't pass them in as int without converting them.

Michael
Nov 17 '05 #15

P: n/a
There's another reason why you wouldn't want to do that, which is that
most C# developers will be accustomed to seeing the first idiom:

if ((SomeEnumValue & SomeEnum.SomeFlag) != 0)
{
}

so if you change the syntax by using a method instead of testing in
open code like this, it will take anyone maintaining the code an extra
second or two to remember what the function does.

Yes, the "standard" syntax isn't pretty, but it _is_ the standard, and
it's what most people will be expecting to see.

Nov 17 '05 #16

P: n/a
You mean there was a point to all this debate? *laughing*.

You will have to do the conversion like in the following example:

public static void Main(String[] args)
{
TestEnum myTest;
myTest = TestEnum.enum2;
myMethod((int)myTest);
}

public static void myMethod(int enumValue )
{
Console.WriteLine(enumValue.ToString());
Console.ReadLine();
}

public enum TestEnum
{
enum1,
enum2,
enum3
}

// Or you can change it to pass the enum and do the conversion in your
method:

public static void Main(String[] args)
{
TestEnum myTest;
myTest = TestEnum.enum2;
myMethod(myTest);
}

public static void myMethod(TestEnum enumValue )
{
Console.WriteLine(((int)enumValue).ToString());
Console.ReadLine();
}
Hope that helps,

Dale Preston

"Michael C" <mc*****@NOSPAMoptushome.com.au> wrote in message
news:#Y*************@TK2MSFTNGP14.phx.gbl...
"Daniel Jin" <Da*******@discussions.microsoft.com> wrote in message
news:0B**********************************@microsof t.com...
back to op, why require the cast? my guess is for type safety. so enum
values are not accidentally passed to a method expecting integer
parameter.
Originally I was trying to replace this code with a function

if ((SomeEnumValue & SomeEnum.SomeFlag) != 0)
{
}

with a function, something like

if(EnumContainsFlag(SomeEnumValue, SomeEnum.SomeFlag))

But I can't pass them in as System.Enum becuase I can't convert them to

int and I can't pass them in as int without converting them.

Michael

Nov 17 '05 #17

P: n/a
Dale Preston <da******@nospam.nospam> wrote:
This is from the C# specification in the Visual Studio documentation:

"The type System.Enum is the abstract base class of all enum types (this is
distinct and different from the underlying type of the enum type), and the
members inherited from System.Enum are available in any enum type."

If enums don't inherit from System.Enum, then what exactly does "abstract
base class" mean in that context? Note that the statement says that the
base class is "distinct and different" from the underlying type of the enum.
The underlying type of the enum is returned by the TypeCode returned from
the instance GetTypeCode method. If the enum does not inherit from
System.Enum, then how is it that the instance enum gets the GetTypeCode
method? It certainly doesn't get it from the underlying type. Int32
doesn't have a GetTypeCode method. And Int32 is sealed and cannot be
inherited from.
The boxed type (the reference type) representing any enum is derived
from System.Enum. The value type doesn't.

It's exactly the same as System.Int32 deriving from System.ValueType,
despite System.ValueType being a reference type in itself. That doesn't
mean that ints always need to be boxed and unboxed - they only do when
there's a conversion to System.ValueType or System.Object.
From the .Net Framework documentation of the System.Enum class:

"Class Enum is derived from class ValueType; that is, Enum is itself a
reference type, not a value type."

Because Enum is a reference type, it must be unboxed to get the integral
underlying type.
Only if you actually *have* an expression of type Enum rather than of
the specific enum type in the first place.
Again, from the C# specification:

"an unboxing conversion (Section 4.3.2) exists from System.Enum to any enum
type."
Also from the C# specification:

<quote>
The explicit enumeration conversions are:
[...]
From any enum-type to sbyte, byte, short, ushort, int, uint, long,
ulong, char, float, double, or decimal.
</quote>

No mention of boxing there, because there's no need for one.
While many of the guesses about why you have to explicitly cast to get the
integer make logical sense and might be good reasons for the requirement,
they are not supported either by the language specification, by the
framework documentation, or by the object-oriented principals of
inheritance.


Not entirely sure what you mean here, but I believe you're wrong if
you're basing that statement on the idea that enum values are always
boxed.

The language specification *could* have been written such that the
enumeration conversions were implicit rather than explicit - but type
safety would have been lost.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 17 '05 #18

P: n/a

"Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message
news:MP************************@msnews.microsoft.c om...
Dale Preston <da******@nospam.nospam> wrote:
This is from the C# specification in the Visual Studio documentation:

"The type System.Enum is the abstract base class of all enum types (this is distinct and different from the underlying type of the enum type), and the members inherited from System.Enum are available in any enum type."

If enums don't inherit from System.Enum, then what exactly does "abstract base class" mean in that context? Note that the statement says that the
base class is "distinct and different" from the underlying type of the enum. The underlying type of the enum is returned by the TypeCode returned from the instance GetTypeCode method. If the enum does not inherit from
System.Enum, then how is it that the instance enum gets the GetTypeCode
method? It certainly doesn't get it from the underlying type. Int32
doesn't have a GetTypeCode method. And Int32 is sealed and cannot be
inherited from.
The boxed type (the reference type) representing any enum is derived
from System.Enum. The value type doesn't.


There is no value type of enum. There is an underlying TypeCode that is
used for integral representation of the enum. To get the value type, you
must unbox it. If it were already an int, it wouldn't be necessary to cast
an int as an int. But if you box an int, it is necessary to unbox to get
back to the int. The syntax for unboxing is, coincidentally, the same as
the syntax for an explicit cast.


It's exactly the same as System.Int32 deriving from System.ValueType,
despite System.ValueType being a reference type in itself. That doesn't
mean that ints always need to be boxed and unboxed - they only do when
there's a conversion to System.ValueType or System.Object.
System.Int32 is a value type inheriting from System.ValueType. System.Enum
is a reference type inheriting from System.ValueType. Since we seem to
agree that System.Enum is a reference type, yet it inherits from a value
type, then how did it get to be a reference type? As I first quoted from
the C# specification, it is boxed at runtime. That's the only way to get a
reference type out of a value type.
From the .Net Framework documentation of the System.Enum class:

"Class Enum is derived from class ValueType; that is, Enum is itself a
reference type, not a value type."

Because Enum is a reference type, it must be unboxed to get the integral
underlying type.
Only if you actually *have* an expression of type Enum rather than of
the specific enum type in the first place.

All specific enum instances are of type Enum. Subclasses are always of the
type of the superclass. Basic OOP.
Again, from the C# specification:

"an unboxing conversion (Section 4.3.2) exists from System.Enum to any enum type."
Also from the C# specification:

<quote>
The explicit enumeration conversions are:
[...]
From any enum-type to sbyte, byte, short, ushort, int, uint, long,
ulong, char, float, double, or decimal.
</quote>


There are a lot of explicit conversions possible in the .Net classes. They
do not imply inheritance by the existence of the explicit conversion. In
fact, since a subclass can always be substituted for a superclass, the
opposite could be inferred though it doesn't always hold true.

No mention of boxing there, because there's no need for one.
While many of the guesses about why you have to explicitly cast to get the integer make logical sense and might be good reasons for the requirement, they are not supported either by the language specification, by the
framework documentation, or by the object-oriented principals of
inheritance.
Not entirely sure what you mean here, but I believe you're wrong if
you're basing that statement on the idea that enum values are always
boxed.


Well, there has been argument that enum instances do not inherit from
System.Enum. Again, if they do not, then how do they get the instance
methods of System.Enum? They do not get the instance methods of
System.Int32.

The language specification *could* have been written such that the
enumeration conversions were implicit rather than explicit - but type
safety would have been lost.
But it wasn't.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too

Dale
Nov 17 '05 #19

P: n/a
"Bruce Wood" <br*******@canada.com> wrote in message
news:11*********************@o13g2000cwo.googlegro ups.com...
There's another reason why you wouldn't want to do that, which is that
most C# developers will be accustomed to seeing the first idiom:

if ((SomeEnumValue & SomeEnum.SomeFlag) != 0)
{
}

so if you change the syntax by using a method instead of testing in
open code like this, it will take anyone maintaining the code an extra
second or two to remember what the function does.

Yes, the "standard" syntax isn't pretty, but it _is_ the standard, and
it's what most people will be expecting to see.


I don't think it would be much of a problem and once they worked it out it
would be clearer to them. With the above format is't easy to mix up the
brackets and & signs, especially when there are several checks in an if
statement. But that would only be the case if it were possible to write it
in a simple form, which it doesn't look possible.

Michael
Nov 17 '05 #20

P: n/a
Dale,

Consider this code:

class App
{
static void Main(string[] args)
{
Foo f = Foo.One;
int i = (int)f;
}
}
enum Foo
{
One,
Two
}

if you look at the IL for Main you see:

.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// Code size 5 (0x5)
.maxstack 1
.locals init ([0] valuetype Foo f,
[1] int32 i)
IL_0000: ldc.i4.0
IL_0001: stloc.0
IL_0002: ldloc.0
IL_0003: stloc.1
IL_0004: ret
} // end of method App::Main
Notice there is no unbox instruction. So your assertion that the "cast" is actually an unbox operation is incorrect. The cast operator is abused in several situations. Its used for type coercion of reference types; its used for numeric conversion of value types and its used for boxing and unboxing. The enum is a value type with an associated numeric value. This is held in the value__ member of the enum and is typed to the type after the colon in the enum definition (or int32 if its omitted).

Regards

Richard Blewett - DevelopMentor
http://www.dotnetconsult.co.uk/weblog
http://www.dotnetconsult.co.uk
There is no value type of enum. There is an underlying TypeCode that is
used for integral representation of the enum. To get the value type, you
must unbox it. If it were already an int, it wouldn't be necessary to cast
an int as an int. But if you box an int, it is necessary to unbox to get
back to the int. The syntax for unboxing is, coincidentally, the same as
the syntax for an explicit cast.

Nov 17 '05 #21

P: n/a
Well, I certainly don't mean to be argumentative about it or to go down with
the ship defending a point that I can't seem to prove [smiling].

I have never disassembled a boxing or unboxing operation to see what it
would look like so I don't know how to respond to what you say. I only know
that an enum is definitely an instance of System.Enum - proven by the fact
that it inherits the instance methods of System.Enum, and that System.Enum
is a reference type, as documented in the C# and .Net Framework
documentation.

I suppose the most important issue is that the syntax of the cast operator
must be used to solve the OP's original question. Whether it is a cast or
an unboxing doesn't make any difference in the end.

It has certainly been an interesting and entertaining discussion though.

Dale
"Richard Blewett [DevelopMentor]" <ri******@NOSPAMdevelop.com> wrote in
message news:uj**************@TK2MSFTNGP10.phx.gbl...
Dale,

Consider this code:

class App
{
static void Main(string[] args)
{
Foo f = Foo.One;
int i = (int)f;
}
}
enum Foo
{
One,
Two
}

if you look at the IL for Main you see:

.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// Code size 5 (0x5)
.maxstack 1
.locals init ([0] valuetype Foo f,
[1] int32 i)
IL_0000: ldc.i4.0
IL_0001: stloc.0
IL_0002: ldloc.0
IL_0003: stloc.1
IL_0004: ret
} // end of method App::Main
Notice there is no unbox instruction. So your assertion that the "cast" is actually an unbox operation is incorrect. The cast operator is abused in
several situations. Its used for type coercion of reference types; its used
for numeric conversion of value types and its used for boxing and unboxing.
The enum is a value type with an associated numeric value. This is held in
the value__ member of the enum and is typed to the type after the colon in
the enum definition (or int32 if its omitted).
Regards

Richard Blewett - DevelopMentor
http://www.dotnetconsult.co.uk/weblog
http://www.dotnetconsult.co.uk
There is no value type of enum. There is an underlying TypeCode that is
used for integral representation of the enum. To get the value type, you
must unbox it. If it were already an int, it wouldn't be necessary to cast an int as an int. But if you box an int, it is necessary to unbox to get
back to the int. The syntax for unboxing is, coincidentally, the same as
the syntax for an explicit cast.

Nov 17 '05 #22

P: n/a
Dale Preston <da******@nospam.nospam> wrote:
The boxed type (the reference type) representing any enum is derived
from System.Enum. The value type doesn't.
There is no value type of enum. There is an underlying TypeCode that is
used for integral representation of the enum. To get the value type, you
must unbox it. If it were already an int, it wouldn't be necessary to cast
an int as an int. But if you box an int, it is necessary to unbox to get
back to the int. The syntax for unboxing is, coincidentally, the same as
the syntax for an explicit cast.


No, value types *are* enums.
It's exactly the same as System.Int32 deriving from System.ValueType,
despite System.ValueType being a reference type in itself. That doesn't
mean that ints always need to be boxed and unboxed - they only do when
there's a conversion to System.ValueType or System.Object.


System.Int32 is a value type inheriting from System.ValueType. System.Enum
is a reference type inheriting from System.ValueType. Since we seem to
agree that System.Enum is a reference type, yet it inherits from a value
type, then how did it get to be a reference type? As I first quoted from
the C# specification, it is boxed at runtime. That's the only way to get a
reference type out of a value type.


No, System.Enum doesn't inherit from a value type. It inherit from a
reference type, System.ValueType.

An enum value is only boxed when it needs to be - when it's
passed/declared/used/whatever as System.Enum, System.ValueType or
System.Object - just as an int is only boxed when it's used as
System.ValueType or System.Object (or interfaces).
Because Enum is a reference type, it must be unboxed to get the integral
underlying type.


Only if you actually *have* an expression of type Enum rather than of
the specific enum type in the first place.


All specific enum instances are of type Enum. Subclasses are always of the
type of the superclass. Basic OOP.


No, an unboxed enum value *isn't* actually of type System.Enum. It's
just convertible to Enum by boxing - same as an int value isn't
actually of type System.ValueType unless it's boxed.
Also from the C# specification:

<quote>
The explicit enumeration conversions are:
[...]
From any enum-type to sbyte, byte, short, ushort, int, uint, long,
ulong, char, float, double, or decimal.
</quote>


There are a lot of explicit conversions possible in the .Net classes. They
do not imply inheritance by the existence of the explicit conversion. In
fact, since a subclass can always be substituted for a superclass, the
opposite could be inferred though it doesn't always hold true.


I've never claimed there's inheritance going on here - I'm claiming
that enum values aren't boxed unless they need to be, contrary to your
idea that they're *always* boxed.
Not entirely sure what you mean here, but I believe you're wrong if
you're basing that statement on the idea that enum values are always
boxed.


Well, there has been argument that enum instances do not inherit from
System.Enum.


And indeed they don't, unless they're boxed.

From the CIL specification, section 8.9.10:
<quote>
Value Types, in their unboxed form, do not inherit from any type. Boxed
value types shall inherit directly from System.ValueType unless they
are enumerations, in which case they shall inherit from System.Enum.
Boxed value types shall be sealed.
</quote>

Note the first part carefully.
Again, if they do not, then how do they get the instance
methods of System.Enum?
They get them when they're boxed.
They do not get the instance methods of System.Int32.


Irrelevant.
The language specification *could* have been written such that the
enumeration conversions were implicit rather than explicit - but type
safety would have been lost.


But it wasn't.


Indeed - and type safety is the reason, not boxing.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 17 '05 #23

P: n/a
Dale Preston <da******@nospam.nospam> wrote:
Well, I certainly don't mean to be argumentative about it or to go down with
the ship defending a point that I can't seem to prove [smiling].

I have never disassembled a boxing or unboxing operation to see what it
would look like so I don't know how to respond to what you say. I only know
that an enum is definitely an instance of System.Enum - proven by the fact
that it inherits the instance methods of System.Enum, and that System.Enum
is a reference type, as documented in the C# and .Net Framework
documentation.
By your logic, that would make *all* types reference types, as
System.Object and even System.ValueType are reference types.

The answer is that enums *don't* actually derive from System.Enum in
their unboxed form, just as (say) an Int32 doesn't actually derive from
System.ValueType in its unboxed form.
I suppose the most important issue is that the syntax of the cast operator
must be used to solve the OP's original question. Whether it is a cast or
an unboxing doesn't make any difference in the end.


It makes a *huge* difference! Enums would be much less efficient if
they were really reference types, just as all the primitive types would
be. It's very important that they really are value types.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 17 '05 #24

P: n/a
Jon Skeet [C# MVP] <sk***@pobox.com> wrote:
Dale Preston <da******@nospam.nospam> wrote:
The boxed type (the reference type) representing any enum is derived
from System.Enum. The value type doesn't.


There is no value type of enum. There is an underlying TypeCode that is
used for integral representation of the enum. To get the value type, you
must unbox it. If it were already an int, it wouldn't be necessary to cast
an int as an int. But if you box an int, it is necessary to unbox to get
back to the int. The syntax for unboxing is, coincidentally, the same as
the syntax for an explicit cast.


No, value types *are* enums.


Whoops, got that backwards - enums *are* value types :)

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 17 '05 #25

P: n/a
Yes, but this was the OP's point.

If he writes the HasFlag method so that it takes int's as arguments,
then he can do the & operation inside the method and come up with a
true / false answer, but he has to call it like this:

if (HasFlag((int)enumValue, (int)Enumeration.EnumFlag)) { ... }

with the ugly (int) casts in there.

On the other hand, if he makes the arguments System.Enum, he doesn't
need an explicit cast (but suffers unwanted boxing), but worse yet he
can't do anything with the boxed values inside the method. C# won't let
him cast a System.Enum to an int, and he can't perform an & operation
on Enums, so he can't calculate the answer.

As I said, I think that the original syntax, as complex as it looks, is
the best way to go, but then that's a matter of taste. :)

Nov 17 '05 #26

P: n/a
Bruce Wood <br*******@canada.com> wrote:
Yes, but this was the OP's point.

If he writes the HasFlag method so that it takes int's as arguments,
then he can do the & operation inside the method and come up with a
true / false answer, but he has to call it like this:

if (HasFlag((int)enumValue, (int)Enumeration.EnumFlag)) { ... }

with the ugly (int) casts in there.

On the other hand, if he makes the arguments System.Enum, he doesn't
need an explicit cast (but suffers unwanted boxing), but worse yet he
can't do anything with the boxed values inside the method. C# won't let
him cast a System.Enum to an int, and he can't perform an & operation
on Enums, so he can't calculate the answer.

As I said, I think that the original syntax, as complex as it looks, is
the best way to go, but then that's a matter of taste. :)


In fact, with a bit of jiggery pokery, it can be done:

using System;

class Test
{
enum Foo
{
Bar,
Baz
}

static void Main()
{
long l1 = ConvertToLong (Foo.Bar);
long l2 = ConvertToLong (Foo.Baz);

Console.WriteLine (l1);
Console.WriteLine (l2);
}

static long ConvertToLong (Enum e)
{
object o = Convert.ChangeType(e,
Enum.GetUnderlyingType(e.GetType()));

return Convert.ToInt64 (o);
}
}

I dread to think of the performance penalties involved, but I believe
it should work for all enums *except* those with an underlying type of
ulong which have values greater then long.MaxValue in them. (You could
convert to ulong instead, but then you'd have trouble with enums with
negative values.)

I'm not suggesting this is a good idea, just thought I'd point it out
:)

Having looked again, here's a somewhat simpler (and more efficient)
implementation with the same limitation:

static long ConvertToLong (Enum e)
{
return ((IConvertible)e).ToInt64(null);
}

(With a bit more effort it would be possible to work round the
limitation to get it to return a negative value in case of overflow,
but I'm not going there just now...)

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 17 '05 #27

P: n/a

As I said, I think that the original syntax, as complex as it looks, is
the best way to go, but then that's a matter of taste. :)


It certainly is the best we have, but thats a failing in the language, IMHO,
;). One of the small handful of things I don't particularly like about the
language.
Nov 17 '05 #28

P: n/a
Daniel O'Connell [C# MVP] <onyxkirx@--NOSPAM--comcast.net> wrote:
As I said, I think that the original syntax, as complex as it looks, is
the best way to go, but then that's a matter of taste. :)


It certainly is the best we have, but thats a failing in the
language, IMHO, ;). One of the small handful of things I don't
particularly like about the language.


Out of interest, what would your preferred fix be? I certainly wouldn't
like the conversion to an int to be implicit, but I agree that there
ought to be some better way of handling this.

Out of interest, are generics going to help here? I haven't looked at
them in terms of enums yet.

(For a bit of fun, have a look at how the Java enum base class is
defined: "public abstract class Enum<E extends Enum<E>>". It always
takes me a while of thinking about it before I understand exactly what
it means :)
--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 17 '05 #29

P: n/a

"Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message
news:MP**********************@msnews.microsoft.com ...
Daniel O'Connell [C# MVP] <onyxkirx@--NOSPAM--comcast.net> wrote:
> As I said, I think that the original syntax, as complex as it looks, is
> the best way to go, but then that's a matter of taste. :)
It certainly is the best we have, but thats a failing in the
language, IMHO, ;). One of the small handful of things I don't
particularly like about the language.


Out of interest, what would your preferred fix be? I certainly wouldn't
like the conversion to an int to be implicit, but I agree that there
ought to be some better way of handling this.


Perhaps I misread Bruces meaning or I'm misreading yours, but I figured he
was talking about
if ((SomeEnumValue & SomeEnum.SomeFlag) != 0)

just to make sure we are on the same page.

I agree implicitly converting to int is not the right answer. The compiler
would need to offer more complete support for enums and their logic. I've
been playing with syntax for flag enums to clarify them significantly for a
long time, but never really found anything I liked. The best I coudl come up
with was pseudo member methods

EnumType enum = <whatever>;

enum.IsSet(EnumType.A);

but that leaves a unpleasent taste of inconsistency and falseness in ones
mouth. Anything else would require either a new keyword or a new use for
one.

I thought about ridiculous ones like

if (Enum.Element is set in val)

or

if (is set(Enum.Element, val))

but those are a bit odd aswell. Any thoughts of your own? For that matter
does anyone know how Delphi deals with this? Or how java will?
Out of interest, are generics going to help here? I haven't looked at
them in terms of enums yet.
It doesn't appear so. Generics cannot use System.Enum as a constraint, so
something like
IsFlagSet<T>(T enumValue, T flag) where T : System.Enum {}
won't work.

(For a bit of fun, have a look at how the Java enum base class is
defined: "public abstract class Enum<E extends Enum<E>>". It always
takes me a while of thinking about it before I understand exactly what
it means :)


Man, that is a bit of a twister isn't it. I'll have a closer look at it, I"m
not sure I can figure out the point without seeing the body, ;).
Nov 17 '05 #30

P: n/a
Daniel O'Connell [C# MVP] <onyxkirx@--NOSPAM--comcast.net> wrote:
Out of interest, what would your preferred fix be? I certainly wouldn't
like the conversion to an int to be implicit, but I agree that there
ought to be some better way of handling this.
Perhaps I misread Bruces meaning or I'm misreading yours, but I figured he
was talking about
if ((SomeEnumValue & SomeEnum.SomeFlag) != 0)

just to make sure we are on the same page.


Yup.
I agree implicitly converting to int is not the right answer. The compiler
would need to offer more complete support for enums and their logic. I've
been playing with syntax for flag enums to clarify them significantly for a
long time, but never really found anything I liked. The best I coudl come up
with was pseudo member methods

EnumType enum = <whatever>;

enum.IsSet(EnumType.A);

but that leaves a unpleasent taste of inconsistency and falseness in ones
mouth. Anything else would require either a new keyword or a new use for
one.
I'm not sure it would need to be a "pseudo" method - what's wrong with
it being a real method?
I thought about ridiculous ones like

if (Enum.Element is set in val)

or

if (is set(Enum.Element, val))

but those are a bit odd aswell. Any thoughts of your own? For that matter
does anyone know how Delphi deals with this? Or how java will?


Java has an EnumSet type, but then its enums are rather different -
they're reference types, and are basically just a bit of compiler help
for switch statements and syntactic over the historic strongly typed
way of doing things. In general they're very nice though - it's good
being able to define methods on enums, and override them on a per case
basis.
Out of interest, are generics going to help here? I haven't looked at
them in terms of enums yet.


It doesn't appear so. Generics cannot use System.Enum as a constraint, so
something like
IsFlagSet<T>(T enumValue, T flag) where T : System.Enum {}
won't work.


Right.
(For a bit of fun, have a look at how the Java enum base class is
defined: "public abstract class Enum<E extends Enum<E>>". It always
takes me a while of thinking about it before I understand exactly what
it means :)


Man, that is a bit of a twister isn't it. I'll have a closer look at it, I"m
not sure I can figure out the point without seeing the body, ;).


There's a page somewhere explaining what it's all about, but it's
basically a way of saying "I'm E!" so that all enums can automatically
declare themselves to implement Comparable<the_same_enum> etc.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 17 '05 #31

P: n/a

"Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message
news:MP************************@msnews.microsoft.c om...
Daniel O'Connell [C# MVP] <onyxkirx@--NOSPAM--comcast.net> wrote:
> Out of interest, what would your preferred fix be? I certainly wouldn't
> like the conversion to an int to be implicit, but I agree that there
> ought to be some better way of handling this.


Perhaps I misread Bruces meaning or I'm misreading yours, but I figured
he
was talking about
if ((SomeEnumValue & SomeEnum.SomeFlag) != 0)

just to make sure we are on the same page.


Yup.
I agree implicitly converting to int is not the right answer. The
compiler
would need to offer more complete support for enums and their logic. I've
been playing with syntax for flag enums to clarify them significantly for
a
long time, but never really found anything I liked. The best I coudl come
up
with was pseudo member methods

EnumType enum = <whatever>;

enum.IsSet(EnumType.A);

but that leaves a unpleasent taste of inconsistency and falseness in ones
mouth. Anything else would require either a new keyword or a new use for
one.


I'm not sure it would need to be a "pseudo" method - what's wrong with
it being a real method?


Primarily that I cannot change the runtime to require a given method but
could provide a language deriative that uses a psuedo-method. The current
runtime always pukes and dies when I try to generate an enum with a method,
so I assume it doesn't permit it(although I"m pretty sure the spec doesn't
disallow it exactly).

Assuming one could add methods to enums, you'd still have other languages to
contend with (VB might not, for example), so using a psuedo method would
boost consistency. The other primary argument would be the psuedomethod
would basically be a macro generating the equivilent logic code as we use
these days, just hidden behind cleaner syntax. A method would require
atleast a pair of stack loads, an invocation, then a pair of stack loads, an
and instruction, and a comparison, while a psuedo method could be
shortcutted to only a pair of stack loads, an and, and a compare. (The
compare might be shaved off both, I can't recall IL well enough off hand to
say for sure though)

My ideas are always primarily C# only and have to be put together without
extra runtime support. If MS or the ECMA decides they are good ones and
chose to modify the runtime or CLS to support them in cleaner fashion, then
more power to them. I just lack the muscle to pull that off.
Man, that is a bit of a twister isn't it. I'll have a closer look at it,
I"m
not sure I can figure out the point without seeing the body, ;).


There's a page somewhere explaining what it's all about, but it's
basically a way of saying "I'm E!" so that all enums can automatically
declare themselves to implement Comparable<the_same_enum> etc.


Ahh, much as I expected. I have a couple classes that are an awful lot like
that written myself to support making a generic tree's root a node as well.
Nov 17 '05 #32

This discussion thread is closed

Replies have been disabled for this discussion.