enum annoyance...

G

Guest

I realize that C# is a strongly typed language, but as a C++ programmer converting to C# I find the requirement that I typecast my integer enum values to be particularly annoying. Does anyone else in the C# community think that the compiler should relax this a bit

// example, define an enum that derives from an int type

public enum Fruit : in

Apple = 1
Banana = 2
Cherry = 3
Date = 4
// etc..


// later in my code I want to use the fruit enum to index some arrays

stock[ Fruit.Apple ] += ( received[ Fruit.Apple ] - shipped[ Fruit.Apple ] )

// I have already told the compiler in my enum declaration that a Fruit is an integer, so why
// do I have to do it this way

stock[ (int) Fruit.Apple ] += ( received[ (int) Fruit.Apple ] - shipped[ (int) Fruit.Apple ] )

// just seems like a lot of unnecessary typing to me...

Sorry to gripe, but this is one place I can post it where somebody who can actually do something about it might see it :-

-- Steve
 
J

Jon Skeet [C# MVP]

sloughin said:
I realize that C# is a strongly typed language, but as a C++
programmer converting to C# I find the requirement that I typecast my
integer enum values to be particularly annoying. Does anyone else in
the C# community think that the compiler should relax this a bit?

Personally, no.
// example, define an enum that derives from an int type:

public enum Fruit : int
{
Apple = 1,
Banana = 2,
Cherry = 3,
Date = 4,
// etc...
}

// later in my code I want to use the fruit enum to index some arrays:

stock[ Fruit.Apple ] += ( received[ Fruit.Apple ] - shipped[ Fruit.Apple ] );

// I have already told the compiler in my enum declaration that a
// Fruit is an integer, so why do I have to do it this way:

A Fruit *isn't* an integer - it's a Fruit. It's just that you've told
the compiler there's a relationship between Fruits and ints, namely
that any Fruit can be represented as an int.
stock[ (int) Fruit.Apple ] += ( received[ (int) Fruit.Apple ] -
shipped[ (int) Fruit.Apple ] );

// just seems like a lot of unnecessary typing to me...

Sorry to gripe, but this is one place I can post it where somebody
who can actually do something about it might see it :)

And where I for one hope no-one will do anything about it :)

You could always write a FruitCollection which used Fruit as the
indexer - but Fruit *isn't* the parameter for any array indexer, and I
don't want to accidentally use a Fruit where I really mean an int.
 
B

Bruno Jouhier [MVP]

a Fruit is a Fruit.

It may be represented as an integer but it is a Fruit.

I don't think that this rule should be relaxed. The cast is very helpful, it
shows that you are doing something that depends on the internal
representation of your Fruit enum. All the rest (stuff that does not need
casting) is "safe" stuff that does not assume anything special about the
representation of your enum.

Bruno

sloughin said:
I realize that C# is a strongly typed language, but as a C++ programmer
converting to C# I find the requirement that I typecast my integer enum
values to be particularly annoying. Does anyone else in the C# community
think that the compiler should relax this a bit?
// example, define an enum that derives from an int type:

public enum Fruit : int
{
Apple = 1,
Banana = 2,
Cherry = 3,
Date = 4,
// etc...
}

// later in my code I want to use the fruit enum to index some arrays:

stock[ Fruit.Apple ] += ( received[ Fruit.Apple ] - shipped[ Fruit.Apple ] );

// I have already told the compiler in my enum declaration that a Fruit is an integer, so why
// do I have to do it this way:

stock[ (int) Fruit.Apple ] += ( received[ (int) Fruit.Apple ] -
shipped[ (int) Fruit.Apple ] );
// just seems like a lot of unnecessary typing to me...

Sorry to gripe, but this is one place I can post it where somebody who can
actually do something about it might see it :)
 
T

Tom Porterfield

sloughin said:
I realize that C# is a strongly typed language, but as a C++
programmer converting to C# I find the requirement that I typecast my
integer enum values to be particularly annoying. Does anyone else in
the C# community think that the compiler should relax this a bit?

// example, define an enum that derives from an int type:

public enum Fruit : int
{
Apple = 1,
Banana = 2,
Cherry = 3,
Date = 4,
// etc...
}

// later in my code I want to use the fruit enum to index some arrays:

stock[ Fruit.Apple ] += ( received[ Fruit.Apple ] - shipped[
Fruit.Apple ] );

// I have already told the compiler in my enum declaration that a
Fruit is an integer, so why // do I have to do it this way:

stock[ (int) Fruit.Apple ] += ( received[ (int) Fruit.Apple ] -
shipped[ (int) Fruit.Apple ] );

// just seems like a lot of unnecessary typing to me...

Sorry to gripe, but this is one place I can post it where somebody
who can actually do something about it might see it :)

Unlike Jon and Bruno, I agree with you. By default the underlying type for
enum is int. However you can specify any integral type except char as the
underlying type for enum. I think the compiler should be smart enough to
know what the underlying type is for the enum and not force you to cast.
--
Tom Porterfield
MS-MVP MCE
http://support.telop.org

Please post all follow-ups to the newsgroup only.
 
C

Charles Law

Hi Tom

I don't think it is lack of smartness on the part of the compiler that is
the problem. The compiler is being quite smart enough when it declares that
you cannot set a fruit to an int. The fact that a fruit is represented
internally by an int is purely incidental. Externally, fruit is a set which
contains apple, orange, pear, etc. Unless you tell the compiler, explicitly,
that it can interpret 4 as a fruit then it should quite rightly get upset.

Charles


Tom Porterfield said:
sloughin said:
I realize that C# is a strongly typed language, but as a C++
programmer converting to C# I find the requirement that I typecast my
integer enum values to be particularly annoying. Does anyone else in
the C# community think that the compiler should relax this a bit?

// example, define an enum that derives from an int type:

public enum Fruit : int
{
Apple = 1,
Banana = 2,
Cherry = 3,
Date = 4,
// etc...
}

// later in my code I want to use the fruit enum to index some arrays:

stock[ Fruit.Apple ] += ( received[ Fruit.Apple ] - shipped[
Fruit.Apple ] );

// I have already told the compiler in my enum declaration that a
Fruit is an integer, so why // do I have to do it this way:

stock[ (int) Fruit.Apple ] += ( received[ (int) Fruit.Apple ] -
shipped[ (int) Fruit.Apple ] );

// just seems like a lot of unnecessary typing to me...

Sorry to gripe, but this is one place I can post it where somebody
who can actually do something about it might see it :)

Unlike Jon and Bruno, I agree with you. By default the underlying type for
enum is int. However you can specify any integral type except char as the
underlying type for enum. I think the compiler should be smart enough to
know what the underlying type is for the enum and not force you to cast.
--
Tom Porterfield
MS-MVP MCE
http://support.telop.org

Please post all follow-ups to the newsgroup only.
 
T

Tom Porterfield

Charles said:
Hi Tom

I don't think it is lack of smartness on the part of the compiler
that is the problem. The compiler is being quite smart enough when it
declares that you cannot set a fruit to an int. The fact that a fruit
is represented internally by an int is purely incidental. Externally,
fruit is a set which contains apple, orange, pear, etc. Unless you
tell the compiler, explicitly, that it can interpret 4 as a fruit
then it should quite rightly get upset.

I disagree that the fact that the underlying data type for Fruit is int is
purely incidental. I could specify some other integral type as the
underlying data type if it suited my needs. If the underlying type of Fruit
is int, and Fruit.Date is given a value of 4, then why shouldn't the
compiler be able to understand that Fruit.Date and 4 are equivalent without
the developer having to explicitly cast (int)Fruit.Date? The cast is
explicitly telling the compiler something that is implicitly known.

I understand the fundamentals of why the cast is required, I just disagree
that the behavior is the correct behavior.
--
Tom Porterfield
MS-MVP MCE
http://support.telop.org

Please post all follow-ups to the newsgroup only.
 
C

Charles Law

I think we may end up agreeing to disagree ;-), but ...

The point of abstraction is that internal and external representation are
decoupled, and therefore, by definition, Fruit.Date and 4 are _not_
equivalent. The compiler is really being generous in allowing the assignment
to take place even with the cast.

Furthermore, are Fruit.Date and 4.0 equivalent? If you assign a double in
place of a Fruit.Date, should the compiler first attempt to convert the
double to an int and then make the assignment?

I'm currently with Jon and Bruno on this one.

Charles
 
B

Bruno Jouhier [MVP]

I agree. Fruit.Date and 4 are not equivalent. Fruit.Date has lots of
calories and 4 is a square number. And I am very happy that the compiler can
make this difference and give me an error if I use one instead of the other.
Relaxing this rule would basically mean that you start giving up on the
distinction between types and their representation.

Bruno.
 
J

Jeff

Original posting seemed to got lost, I apologize if this response gets
duped.
I understand the fundamentals of why the cast is required, I just disagree
that the behavior is the correct behavior.

The C# spec states that an explicit cast is needed to go from the enum to
its underlying type and from the underlying type to the enum. So it is the
correct and intended behavior.

The CLI spec states the explicit casts are not needed so it seems the cast
is enforced by C# language compiler itself.

Interesting thing though, the C# spec says the following statement is legal,
even if none of the enum fields are defined as 0:
Fruit F=0;
Low and behold it compiles, but the following does not without an explicit
cast:
Fruit F=1;

Any ideas why spec allows this?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top