Hi!
I have created an enum list like this:
enum myEnum : int
{
This = 2,
That,
NewVal = 10,
LastItm
}
When using the enum, why do i have to cast the value?
int aValue = (int)myEnum.This;
should it not just do with...
int aValue = myEnum.That; ?
Regards
Martin Arvidsson 18 11204
Because a value of an enum-type is not a number.
"Visual Systems AB (Martin Arvidsson)" <ma**************@vsab.net> schrieb
im Newsbeitrag news:u2*************@TK2MSFTNGP15.phx.gbl... Hi!
I have created an enum list like this:
enum myEnum : int { This = 2, That, NewVal = 10, LastItm }
When using the enum, why do i have to cast the value?
int aValue = (int)myEnum.This;
should it not just do with...
int aValue = myEnum.That; ?
Regards
Martin Arvidsson
Visual Systems AB (Martin Arvidsson) wrote: Hi!
I have created an enum list like this:
enum myEnum : int { This = 2, That, NewVal = 10, LastItm }
When using the enum, why do i have to cast the value?
int aValue = (int)myEnum.This;
should it not just do with...
int aValue = myEnum.That; ?
Regards
Martin Arvidsson
you *should* use
myEnum aValue = myEnum.This;
the enum is a separate type, not just a way to specify a list of integer constants.
So if you want to convert an enum value to an int, you have to cast ...
Hans Kesting
An enum is a class. See the Enum class in the .Net framework.
Normally you do not want to cast an enum to an int. And if you do, you have
to do so explicitly.\
Really, you should avoid assigning values to the enum. The compiler will do
this for you. (If you are trying to make a set of bit flags, be sure to use
the [Flags] attribute. See FlagsAttribute class.)
If is recommended that you would use an enum as follows:
myEnum theEnum = myEnum.That;
if (theEnum == myEnum.LastItm) {
// do something
}
switch (theEnum) {
case: myEnum.This:
// stuff
break;
case: myEnum.That:
// other stuff
break;
// {rest of valid enum values go here}
default:
throw new ArgumentException("Invalid value for theEnum was
specified", "theEnum");
}
Hope this helps...
Frisky
"Visual Systems AB (Martin Arvidsson)" <ma**************@vsab.net> wrote in
message news:u2*************@TK2MSFTNGP15.phx.gbl... Hi!
I have created an enum list like this:
enum myEnum : int { This = 2, That, NewVal = 10, LastItm }
When using the enum, why do i have to cast the value?
int aValue = (int)myEnum.This;
should it not just do with...
int aValue = myEnum.That; ?
Regards
Martin Arvidsson
Frisky <Fr***********@NorthPole.net> wrote: An enum is a class. See the Enum class in the .Net framework.
Actually, an enum is a value type. Enum itself is a reference type, but
every enum is a value type.
Normally you do not want to cast an enum to an int. And if you do, you have to do so explicitly.\
Agreed.
Really, you should avoid assigning values to the enum. The compiler will do this for you.
That entirely depends on the situation. If the enum is mirroring
existing status codes, for example, you almost certainly *do* want to
assign values.
--
Jon Skeet - <sk***@pobox.com> http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Jon,
You are absolutley correct, an enum is a value type. It derives from the
System.ValueType. Bad segway into, look up the documentation under
System.Enum.
I don't have to mirror the values for an external system. All I have to do
is make sure I map the external system in and out.
But, it is not a hard fast rule. The example you gave in particular
instances might be the right way to go. I gave the example of using the enum
as a bit flags. Yep, you gotta use values here.
That is why I used the word "avoid".
Fari enough?
Frisky
"Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message
news:MP************************@msnews.microsoft.c om... Frisky <Fr***********@NorthPole.net> wrote: An enum is a class. See the Enum class in the .Net framework.
Actually, an enum is a value type. Enum itself is a reference type, but every enum is a value type.
Normally you do not want to cast an enum to an int. And if you do, you have to do so explicitly.\
Agreed.
Really, you should avoid assigning values to the enum. The compiler will do this for you.
That entirely depends on the situation. If the enum is mirroring existing status codes, for example, you almost certainly *do* want to assign values.
-- Jon Skeet - <sk***@pobox.com> http://www.pobox.com/~skeet If replying to the group, please do not mail me too
Frisky <Fr***********@NorthPole.net> wrote: You are absolutley correct, an enum is a value type. It derives from the System.ValueType. Bad segway into, look up the documentation under System.Enum.
I don't have to mirror the values for an external system. All I have to do is make sure I map the external system in and out.
But, it is not a hard fast rule. The example you gave in particular instances might be the right way to go. I gave the example of using the enum as a bit flags. Yep, you gotta use values here.
That is why I used the word "avoid".
Fari enough?
I still think "avoid" is a bit too strong without any extra
qualification. I find I need to assign values as often as I don't. It's
probably just a matter of how strong each of us thinks the word
"avoid" is though :)
--
Jon Skeet - <sk***@pobox.com> http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Actually, it's just my opinion. And it works very well for me and my teams.
I very seldom define any enum with numerical values.
Just goes to show there is more than one way to do things.
--
Frisky
Intellectuals solve problems; geniuses prevent them. ~ Albert Einstein
"Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message
news:MP************************@msnews.microsoft.c om... Frisky <Fr***********@NorthPole.net> wrote: You are absolutley correct, an enum is a value type. It derives from the System.ValueType. Bad segway into, look up the documentation under System.Enum.
I don't have to mirror the values for an external system. All I have to do is make sure I map the external system in and out.
But, it is not a hard fast rule. The example you gave in particular instances might be the right way to go. I gave the example of using the enum as a bit flags. Yep, you gotta use values here.
That is why I used the word "avoid".
Fari enough?
I still think "avoid" is a bit too strong without any extra qualification. I find I need to assign values as often as I don't. It's probably just a matter of how strong each of us thinks the word "avoid" is though :)
-- Jon Skeet - <sk***@pobox.com> http://www.pobox.com/~skeet If replying to the group, please do not mail me too
Actually, it's just my opinion. And it works very well for me and my teams.
I very seldom define any enum with numerical values.
Just goes to show there is more than one way to do things.
--
Frisky
Intellectuals solve problems; geniuses prevent them. ~ Albert Einstein
"Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message
news:MP************************@msnews.microsoft.c om... Frisky <Fr***********@NorthPole.net> wrote: You are absolutley correct, an enum is a value type. It derives from the System.ValueType. Bad segway into, look up the documentation under System.Enum.
I don't have to mirror the values for an external system. All I have to do is make sure I map the external system in and out.
But, it is not a hard fast rule. The example you gave in particular instances might be the right way to go. I gave the example of using the enum as a bit flags. Yep, you gotta use values here.
That is why I used the word "avoid".
Fari enough?
I still think "avoid" is a bit too strong without any extra qualification. I find I need to assign values as often as I don't. It's probably just a matter of how strong each of us thinks the word "avoid" is though :)
-- Jon Skeet - <sk***@pobox.com> http://www.pobox.com/~skeet If replying to the group, please do not mail me too
Frisky <Fr***********@NorthPole.net> wrote: Actually, it's just my opinion. And it works very well for me and my teams.
I very seldom define any enum with numerical values.
Just goes to show there is more than one way to do things.
I think it's more that it shows that different people have different
applications. There may well be no case where I would assign values and
you wouldn't, but I deal with a lot of situations where the actual
values are important and you don't.
Certainly I'd agree that there's little point in assigning values when
they're not needed - although if the enum is used by an assembly other
than the one in which it's defined, and the assemblies may need to be
changed independently, changing the contents of the enum without
recompiling the other assembly will lead to out-of-date values being
used unless the values are specified and always kept constant.
For instance, if you have Lib.cs:
public enum Bar
{
Hello,
There
}
compiled to Lib.dll
and Test.cs:
using System;
public class Test
{
static void Main()
{
Bar b = Bar.There;
Console.WriteLine (b);
}
}
Compile Test.cs against Lib.dll, and run it - it prints out "There".
Now change Bar.cs to add a new member (Foo) between Hello and There.
Compile just Bar.cs to get a new Lib.dll, rerun Test and it will print
out "Foo". That wouldn't happen if you'd assigned There a value
explicitly and kept it constant when changing the enum. Of course, this
isn't a problem in many situations, but I thought I'd mention it as
another potential reason for explicit numbering.
--
Jon Skeet - <sk***@pobox.com> http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Frisky <Fr***********@NorthPole.net> wrote: Actually, it's just my opinion. And it works very well for me and my teams.
I very seldom define any enum with numerical values.
Just goes to show there is more than one way to do things.
I think it's more that it shows that different people have different
applications. There may well be no case where I would assign values and
you wouldn't, but I deal with a lot of situations where the actual
values are important and you don't.
Certainly I'd agree that there's little point in assigning values when
they're not needed - although if the enum is used by an assembly other
than the one in which it's defined, and the assemblies may need to be
changed independently, changing the contents of the enum without
recompiling the other assembly will lead to out-of-date values being
used unless the values are specified and always kept constant.
For instance, if you have Lib.cs:
public enum Bar
{
Hello,
There
}
compiled to Lib.dll
and Test.cs:
using System;
public class Test
{
static void Main()
{
Bar b = Bar.There;
Console.WriteLine (b);
}
}
Compile Test.cs against Lib.dll, and run it - it prints out "There".
Now change Bar.cs to add a new member (Foo) between Hello and There.
Compile just Bar.cs to get a new Lib.dll, rerun Test and it will print
out "Foo". That wouldn't happen if you'd assigned There a value
explicitly and kept it constant when changing the enum. Of course, this
isn't a problem in many situations, but I thought I'd mention it as
another potential reason for explicit numbering.
--
Jon Skeet - <sk***@pobox.com> http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
The enum that is defined in your examlpe is the same as any other interface.
It is open for extension but closed for modification. You must be judicious
in how you modify existing interfaces. Especially if I know the enum is not
directly consumed, but externally through someone else's DLL that I can't
recompile. However, your point is a good one, you should always be careful
how you define things that are used externally.
Had you simply added the value at the bottom of the enum list, the existing
applications would work fine.
Personally, all of the systems we build are built from a highly repeatable
SCM system. We have all of our source and build from scratch at each
interval. This avoids this specific problem. I know many are not this lucky.
If you are shipping external software, you should probably have declared the
enum internal unless it had to be pubic. And what gets marked public is
written in stone.
I use enums for many various external system values. We have lots of
external systems and values. But we always compare name to value. Never
compare value to value. I don't think it is so much the applications, as
just how you have learned to implement your systems.
We have a set of best practices that we follow. This is just one of the
practices. The longer we have used this practice, the more we have found
that there are very few reasons to break the practice.
One more tid bit I'll throw in...
If you define your enum like this:
public enum RegistrationStatus {
Registered = 1,
NotRegistered = 2,
}
and now I write the code:
RegistrationStatus registrationStatus = new RegistrationStatus();
this is a problem. Since enum, as we established earlier, is a value type,
the value you registrationStatus is now undefined. That is, since it is a
value type, the default value is 0, which is not a valid value.
--
Frisky
Intellectuals solve problems; geniuses prevent them. ~ Albert Einstein
"Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message
news:MP************************@msnews.microsoft.c om... Frisky <Fr***********@NorthPole.net> wrote: Actually, it's just my opinion. And it works very well for me and my teams.
I very seldom define any enum with numerical values.
Just goes to show there is more than one way to do things.
I think it's more that it shows that different people have different applications. There may well be no case where I would assign values and you wouldn't, but I deal with a lot of situations where the actual values are important and you don't.
Certainly I'd agree that there's little point in assigning values when they're not needed - although if the enum is used by an assembly other than the one in which it's defined, and the assemblies may need to be changed independently, changing the contents of the enum without recompiling the other assembly will lead to out-of-date values being used unless the values are specified and always kept constant.
For instance, if you have Lib.cs: public enum Bar { Hello, There }
compiled to Lib.dll
and Test.cs: using System;
public class Test { static void Main() { Bar b = Bar.There; Console.WriteLine (b); } }
Compile Test.cs against Lib.dll, and run it - it prints out "There". Now change Bar.cs to add a new member (Foo) between Hello and There. Compile just Bar.cs to get a new Lib.dll, rerun Test and it will print out "Foo". That wouldn't happen if you'd assigned There a value explicitly and kept it constant when changing the enum. Of course, this isn't a problem in many situations, but I thought I'd mention it as another potential reason for explicit numbering.
-- Jon Skeet - <sk***@pobox.com> http://www.pobox.com/~skeet If replying to the group, please do not mail me too
The enum that is defined in your examlpe is the same as any other interface.
It is open for extension but closed for modification. You must be judicious
in how you modify existing interfaces. Especially if I know the enum is not
directly consumed, but externally through someone else's DLL that I can't
recompile. However, your point is a good one, you should always be careful
how you define things that are used externally.
Had you simply added the value at the bottom of the enum list, the existing
applications would work fine.
Personally, all of the systems we build are built from a highly repeatable
SCM system. We have all of our source and build from scratch at each
interval. This avoids this specific problem. I know many are not this lucky.
If you are shipping external software, you should probably have declared the
enum internal unless it had to be pubic. And what gets marked public is
written in stone.
I use enums for many various external system values. We have lots of
external systems and values. But we always compare name to value. Never
compare value to value. I don't think it is so much the applications, as
just how you have learned to implement your systems.
We have a set of best practices that we follow. This is just one of the
practices. The longer we have used this practice, the more we have found
that there are very few reasons to break the practice.
One more tid bit I'll throw in...
If you define your enum like this:
public enum RegistrationStatus {
Registered = 1,
NotRegistered = 2,
}
and now I write the code:
RegistrationStatus registrationStatus = new RegistrationStatus();
this is a problem. Since enum, as we established earlier, is a value type,
the value you registrationStatus is now undefined. That is, since it is a
value type, the default value is 0, which is not a valid value.
--
Frisky
Intellectuals solve problems; geniuses prevent them. ~ Albert Einstein
"Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message
news:MP************************@msnews.microsoft.c om... Frisky <Fr***********@NorthPole.net> wrote: Actually, it's just my opinion. And it works very well for me and my teams.
I very seldom define any enum with numerical values.
Just goes to show there is more than one way to do things.
I think it's more that it shows that different people have different applications. There may well be no case where I would assign values and you wouldn't, but I deal with a lot of situations where the actual values are important and you don't.
Certainly I'd agree that there's little point in assigning values when they're not needed - although if the enum is used by an assembly other than the one in which it's defined, and the assemblies may need to be changed independently, changing the contents of the enum without recompiling the other assembly will lead to out-of-date values being used unless the values are specified and always kept constant.
For instance, if you have Lib.cs: public enum Bar { Hello, There }
compiled to Lib.dll
and Test.cs: using System;
public class Test { static void Main() { Bar b = Bar.There; Console.WriteLine (b); } }
Compile Test.cs against Lib.dll, and run it - it prints out "There". Now change Bar.cs to add a new member (Foo) between Hello and There. Compile just Bar.cs to get a new Lib.dll, rerun Test and it will print out "Foo". That wouldn't happen if you'd assigned There a value explicitly and kept it constant when changing the enum. Of course, this isn't a problem in many situations, but I thought I'd mention it as another potential reason for explicit numbering.
-- Jon Skeet - <sk***@pobox.com> http://www.pobox.com/~skeet If replying to the group, please do not mail me too
Frisky <Fr***********@NorthPole.net> wrote: The enum that is defined in your examlpe is the same as any other interface. It is open for extension but closed for modification. You must be judicious in how you modify existing interfaces. Especially if I know the enum is not directly consumed, but externally through someone else's DLL that I can't recompile. However, your point is a good one, you should always be careful how you define things that are used externally.
Had you simply added the value at the bottom of the enum list, the existing applications would work fine.
Absolutely - but you may not *want* to put it at the bottom, for some
reason.
Personally, all of the systems we build are built from a highly repeatable SCM system. We have all of our source and build from scratch at each interval. This avoids this specific problem. I know many are not this lucky. If you are shipping external software, you should probably have declared the enum internal unless it had to be pubic. And what gets marked public is written in stone.
It doesn't have to be if you specify the values though - you can have a
compatible enum but still put the values wherever you like in the
source code, which can often be very useful if you're grouping the
values into regions.
I use enums for many various external system values. We have lots of external systems and values. But we always compare name to value. Never compare value to value. I don't think it is so much the applications, as just how you have learned to implement your systems.
Not sure what you mean by this... but if you were implementing HTTP
status codes, would you have loads of empty entries, just to get up to
the 50x status codes? Surely not.
We have a set of best practices that we follow. This is just one of the practices. The longer we have used this practice, the more we have found that there are very few reasons to break the practice.
Whenever there are external systems which have to be kept in sync in
terms of values, I think you end up with much less brittle software if
everything is explicit.
One more tid bit I'll throw in...
If you define your enum like this:
public enum RegistrationStatus { Registered = 1, NotRegistered = 2, }
and now I write the code:
RegistrationStatus registrationStatus = new RegistrationStatus();
this is a problem. Since enum, as we established earlier, is a value type, the value you registrationStatus is now undefined. That is, since it is a value type, the default value is 0, which is not a valid value.
It's not undefined, it's 0. It's a valid value for the variable, it
just doesn't appear in the set of named values. You can get just as
much of a "problem" if you cast an unknown integer value to the enum.
If that's a problem, just don't do that then - start your values as 0
even if you're hardcoding them.
--
Jon Skeet - <sk***@pobox.com> http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Intellectuals solve problems; geniuses prevent them. ~ Albert Einstein
"Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message
news:MP************************@msnews.microsoft.c om... Frisky <Fr***********@NorthPole.net> wrote: The enum that is defined in your examlpe is the same as any other interface. It is open for extension but closed for modification. You must be judicious in how you modify existing interfaces. Especially if I know the enum is not directly consumed, but externally through someone else's DLL that I can't recompile. However, your point is a good one, you should always be careful how you define things that are used externally.
Had you simply added the value at the bottom of the enum list, the existing applications would work fine. Absolutely - but you may not *want* to put it at the bottom, for some reason.
But you can't. This violates the Open-Close principal. (Software entities
should be open for extension, but closed for modification.)
If you are compiling everything together, this does not make a difference.
It is only for binary compatibility. Personally, all of the systems we build are built from a highly repeatable SCM system. We have all of our source and build from scratch at each interval. This avoids this specific problem. I know many are not this lucky. If you are shipping external software, you should probably have declared the enum internal unless it had to be pubic. And what gets marked public is written in stone.
It doesn't have to be if you specify the values though - you can have a compatible enum but still put the values wherever you like in the source code, which can often be very useful if you're grouping the values into regions.
I guess what your arguing is that what you mark as public does not have to
be written in stone. But, that's a basic design fundamental anyway. Based on
the Open-Closed principle. This does not matter whether you are talking
about a class, a COM object, or in this case, an Enum. It is a public
interface and cannot be modified. It can only be extended. I use enums for many various external system values. We have lots of external systems and values. But we always compare name to value. Never compare value to value. I don't think it is so much the applications, as just how you have learned to implement your systems.
Not sure what you mean by this... but if you were implementing HTTP status codes, would you have loads of empty entries, just to get up to the 50x status codes? Surely not.
I would simply map the status code to the name and vice-versa. But, the
actual value used by the enum could be any number, and would not matter in
the code. The code that is dependent on the enum (other than this mapping)
is not dependent on a specific implementation of that enum. We have a set of best practices that we follow. This is just one of the practices. The longer we have used this practice, the more we have found that there are very few reasons to break the practice.
Whenever there are external systems which have to be kept in sync in terms of values, I think you end up with much less brittle software if everything is explicit.
Actually, I have found that quite the opposite is true. We create an
interface to the external system. The interface is the only piece of code
that knows how to translate code to and from the external system. If the
codes change, I only have one place to change them for conversion.
Internally, its a "who cares". One more tid bit I'll throw in...
If you define your enum like this:
public enum RegistrationStatus { Registered = 1, NotRegistered = 2, }
and now I write the code:
RegistrationStatus registrationStatus = new RegistrationStatus();
this is a problem. Since enum, as we established earlier, is a value type, the value you registrationStatus is now undefined. That is, since it is a value type, the default value is 0, which is not a valid value.
It's not undefined, it's 0. It's a valid value for the variable, it just doesn't appear in the set of named values. You can get just as much of a "problem" if you cast an unknown integer value to the enum.
If that's a problem, just don't do that then - start your values as 0 even if you're hardcoding them.
It is undefined. In the Enum, it was not defined. While it is a valid value
for an Enum, it is not valid for this Enum. If I called a method you were
implementing and sent you a value in an Enum, wouldn't you expect the value
to be one of the defined names? (This is a bug waiting to rear its ugly
head.)
Actually, I thought your argument was that you were using values from an
external system, so that you can map to them. But, if the value has no
significance, and you can just change it to zero at will, why are you
setting the value to begin with? Just let the language do that for you.
Frisky -- Jon Skeet - <sk***@pobox.com> http://www.pobox.com/~skeet If replying to the group, please do not mail me too
Frisky <Fr***********@NorthPole.net> wrote: Absolutely - but you may not *want* to put it at the bottom, for some reason. But you can't. This violates the Open-Close principal. (Software entities should be open for extension, but closed for modification.)
I can't in your way of doing things - but I can add it wherever I like
when I'm assigning values manually, because there's nothing to say that
the order in the source code has to be ascending in value. I can do:
Something = 0,
SomethingIForgotToPutInBefore = 100,
TheOriginalSecondLine = 1
No problem. You can't do that if you don't assign values explicitly.
(You can change to assigning them manually at the point you need to do
the above, of course, so long as you're careful.)
If you are compiling everything together, this does not make a difference. It is only for binary compatibility.
Yes. It doesn't have to be if you specify the values though - you can have a compatible enum but still put the values wherever you like in the source code, which can often be very useful if you're grouping the values into regions.
I guess what your arguing is that what you mark as public does not have to be written in stone.
In what way am I arguing that? In what way is the order in which the
values are defined in source code part of the interface?
But, that's a basic design fundamental anyway. Based on the Open-Closed principle. This does not matter whether you are talking about a class, a COM object, or in this case, an Enum. It is a public interface and cannot be modified. It can only be extended.
Sure. I don't believe that the source code forms part of the interface
though. Not sure what you mean by this... but if you were implementing HTTP status codes, would you have loads of empty entries, just to get up to the 50x status codes? Surely not.
I would simply map the status code to the name and vice-versa.
So you'd use a separate map? That seems a bit of a waste to me.
But, the actual value used by the enum could be any number, and would not matter in the code. The code that is dependent on the enum (other than this mapping) is not dependent on a specific implementation of that enum.
Hang on though - a minute ago you were accusing me of breaking things
by changing numbers (which I wasn't). Now you're suggesting that the
"specific implementation" of the enum (by which I assume you mean the
values) shouldn't be relied upon? We have a set of best practices that we follow. This is just one of the practices. The longer we have used this practice, the more we have found that there are very few reasons to break the practice.
Whenever there are external systems which have to be kept in sync in terms of values, I think you end up with much less brittle software if everything is explicit.
Actually, I have found that quite the opposite is true. We create an interface to the external system. The interface is the only piece of code that knows how to translate code to and from the external system. If the codes change, I only have one place to change them for conversion. Internally, its a "who cares".
Whereas the way I'd do it, you'd still only have one place to change
them for conversion (not that they should be changed, as we've agreed
above) - but that place would also be the definition of the enum. You'd
have one piece of source code doing both jobs, which I believe is more
compact. If an extra code is needed, you only need to add it in one
place rather than two. It's not undefined, it's 0. It's a valid value for the variable, it just doesn't appear in the set of named values. You can get just as much of a "problem" if you cast an unknown integer value to the enum.
If that's a problem, just don't do that then - start your values as 0 even if you're hardcoding them.
It is undefined. In the Enum, it was not defined. While it is a valid value for an Enum, it is not valid for this Enum. If I called a method you were implementing and sent you a value in an Enum, wouldn't you expect the value to be one of the defined names? (This is a bug waiting to rear its ugly head.)
Not necessarily. In particular, if you assume that and you use the MS
HttpStatusCode enumeration, you may find that a webserver has given you
a value you don't understand. If the value is coming from outside your
control, you *should* be defensive about whether or not it's one that
you understand. You don't need to use a map to do that though.
Actually, I thought your argument was that you were using values from an external system, so that you can map to them. But, if the value has no significance, and you can just change it to zero at will, why are you setting the value to begin with? Just let the language do that for you.
You're the one claiming the value should have no signficance, as I
understand it. I'm saying that the value should have the same
significance inside the code as in the external system, for the sake of
clarity and maintenance. If you get passed a value you don't understand
from the external system, you should react appropriately (whatever that
reaction is for the situation.)
--
Jon Skeet - <sk***@pobox.com> http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Intellectuals solve problems; geniuses prevent them. ~ Albert Einstein
"Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message
news:MP************************@msnews.microsoft.c om... Frisky <Fr***********@NorthPole.net> wrote: > Absolutely - but you may not *want* to put it at the bottom, for some > reason. But you can't. This violates the Open-Close principal. (Software entities should be open for extension, but closed for modification.)
I can't in your way of doing things - but I can add it wherever I like when I'm assigning values manually, because there's nothing to say that the order in the source code has to be ascending in value. I can do:
Something = 0, SomethingIForgotToPutInBefore = 100, TheOriginalSecondLine = 1
No problem. You can't do that if you don't assign values explicitly. (You can change to assigning them manually at the point you need to do the above, of course, so long as you're careful.)
But why in the world world would it make a difference where I added a value
in an Enum other than esthetics? (And of course the point we are
discussing.) Assigning them a value only makes them less abstract a more
concreted. In other word, brittle. If you are compiling everything together, this does not make a difference. It is only for binary compatibility.
Yes.
And while we all want binary compatibility, who are the few that have to
deliver on this? And if I am one of those few, I am probably faced with the
Open-Closed principle in point of fact on all of the public code I share. I
just a given. > It doesn't have to be if you specify the values though - you can have a > compatible enum but still put the values wherever you like in the > source code, which can often be very useful if you're grouping the > values into regions.
I guess what your arguing is that what you mark as public does not have to be written in stone.
In what way am I arguing that? In what way is the order in which the values are defined in source code part of the interface?
I am not sure what you were refering to. I did not understand what you meant
by "It doesn't have to be if you specifiy the value though". What is "It"
refering to? I assumed you mean from my previous sentance that the interface
was written in stone.
The enum, if public, is part of you software interface. Interfaces, which
have been around a long time before Java and C# coined the expression, are
any contract between the client and the called code. Right? And as such are
subject to the Open-Closed principle. But, that's a basic design fundamental anyway. Based on the Open-Closed principle. This does not matter whether you are talking about a class, a COM object, or in this case, an Enum. It is a public interface and cannot be modified. It can only be extended.
Sure. I don't believe that the source code forms part of the interface though.
Any part of the contract is part of the interface. If you supply a type,
Enum, or other portions of code as public, you are supplying them to fufill
the contract. If you change the enum that your method takes, you
fundamentally have changed that contract. If the client of that code uses a
method that takes the same arguments, including the Enum you changed, then
did the method change, or is it the same? What if the method now does not
throw (or return an error, or null :) like it used to because a value has
been added to the Enum. But, the client code expects that to be an error.
That could be a bug. And one that is hard to detect, because there is no
error now. It was a contract, and the the contract was broken. > Not sure what you mean by this... but if you were implementing HTTP > status codes, would you have loads of empty entries, just to get up to > the 50x status codes? Surely not.
I would simply map the status code to the name and vice-versa.
So you'd use a separate map? That seems a bit of a waste to me.
Has worked very well for me in the few places where I actually need it. And
its not a data map, but a mapping class. But, the actual value used by the enum could be any number, and would not matter in the code. The code that is dependent on the enum (other than this mapping) is not dependent on a specific implementation of that enum.
Hang on though - a minute ago you were accusing me of breaking things by changing numbers (which I wasn't). Now you're suggesting that the "specific implementation" of the enum (by which I assume you mean the values) shouldn't be relied upon?
This is the very point I have been suggesting all along. The code should not
use explicit values of an Enum. (Except the case as aformentioned when you
are using a bit flag, or other compelling reason.) >> We have a set of best practices that we follow. This is just one of >> the >> practices. The longer we have used this practice, the more we have >> found >> that there are very few reasons to break the practice. > > Whenever there are external systems which have to be kept in sync in > terms of values, I think you end up with much less brittle software if > everything is explicit.
Actually, I have found that quite the opposite is true. We create an interface to the external system. The interface is the only piece of code that knows how to translate code to and from the external system. If the codes change, I only have one place to change them for conversion. Internally, its a "who cares".
Whereas the way I'd do it, you'd still only have one place to change them for conversion (not that they should be changed, as we've agreed above) - but that place would also be the definition of the enum. You'd have one piece of source code doing both jobs, which I believe is more compact. If an extra code is needed, you only need to add it in one place rather than two.
I think we agree on this. But, are you saying that you too do not use the
value of the Enum after it is assigned? So, you are only using the value as
a means of reading to/from the external or other system that required you to
set them to that value to begin with? Because this is the main part of my
suggestion. I prefer not to assign them or assume anything about their value
(except the bit flag or other compelling case) and use a mapping class to
set them. And from what I think you are saying, this is basically the same,
except you use the actual Enum as you mapping. ???
The only difference, this being the case, is the choice of mapping
technique. > It's not undefined, it's 0. It's a valid value for the variable, it > just doesn't appear in the set of named values. You can get just as > much of a "problem" if you cast an unknown integer value to the enum. > > If that's a problem, just don't do that then - start your values as 0 > even if you're hardcoding them.
It is undefined. In the Enum, it was not defined. While it is a valid value for an Enum, it is not valid for this Enum. If I called a method you were implementing and sent you a value in an Enum, wouldn't you expect the value to be one of the defined names? (This is a bug waiting to rear its ugly head.)
Not necessarily. In particular, if you assume that and you use the MS HttpStatusCode enumeration, you may find that a webserver has given you a value you don't understand. If the value is coming from outside your control, you *should* be defensive about whether or not it's one that you understand. You don't need to use a map to do that though.
I don't know how this would have anything to do with the code in the Enum.
Sure, I would be defensive that I only understand values in the enumeration.
And perhaps, only a subset of those. But I would not assume that, for
example, the HttpStatusCode.OK necessarily equals 200, even though that may
have been the actual code sent back. I would not compare my enum against a
value of 200. I would have no need to do this. I would check against the
enum name. Actually, I thought your argument was that you were using values from an external system, so that you can map to them. But, if the value has no significance, and you can just change it to zero at will, why are you setting the value to begin with? Just let the language do that for you.
You're the one claiming the value should have no signficance, as I understand it. I'm saying that the value should have the same significance inside the code as in the external system, for the sake of clarity and maintenance. If you get passed a value you don't understand from the external system, you should react appropriately (whatever that reaction is for the situation.)
Yes, I am claiming that the value has no significance, or at least should
have not significance. But you said you could just change your value to
start at zero. If it does not matter if its zero or twelve, then what does
it matter at all?
And I am claiming that you must make sure that you correctly take a system
that for example passes an int 200 as the return of a status code for and
http service, and map it to HttpStatusCode.OK (assuming that is how you
would like to use it internally). And then, from there on, who cares if it
was status code 200, 501, 400, etc.? Its a HttpStatusCode.OK. Isn't that
enough? Why would I need to know its internal representation?
-- Jon Skeet - <sk***@pobox.com> http://www.pobox.com/~skeet If replying to the group, please do not mail me too
Frisky <Fr***********@NorthPole.net> wrote: No problem. You can't do that if you don't assign values explicitly. (You can change to assigning them manually at the point you need to do the above, of course, so long as you're careful.) But why in the world world would it make a difference where I added a value in an Enum other than esthetics? (And of course the point we are discussing.)
It makes a *huge* difference if you *don't* assign the values
explicitly, as it changes all the other values.
Assigning them a value only makes them less abstract a more concreted. In other word, brittle.
In my way of doing things, I can add another value anywhere without
changing the rest of the values. In your way of doing things, adding a
value anywhere other than at the end changes at least one value.
In what way is your way *less* brittle than mine? Yes.
And while we all want binary compatibility, who are the few that have to deliver on this? And if I am one of those few, I am probably faced with the Open-Closed principle in point of fact on all of the public code I share. I just a given.
We've been bitten in the past by enums which weren't explicitly valued.
The enums were generated from resource files. The resource assembly
needed to be patched, but one of the assemblies which *didn't* need
patching otherwise use the resources. Suddenly all our messages were
coming out completely garbled. (Fortunately it was obvious, so we
caught the problem in time :)
Now the enum generation makes sure that it keeps the same values
forever. I guess what your arguing is that what you mark as public does not have to be written in stone.
In what way am I arguing that? In what way is the order in which the values are defined in source code part of the interface?
I am not sure what you were refering to. I did not understand what you meant by "It doesn't have to be if you specifiy the value though". What is "It" refering to? I assumed you mean from my previous sentance that the interface was written in stone.
I don't see what you're asking, I'm afraid.
I believe you can have a public interface which *is* written in stone
(extensible - you can add elements) and make life easier for yourself
by explicitly stating those values.
Somehow you took from my post that I was arguing that what you mark as
public does *not* have to be written in stone, and I can't see how that
follows at all.
The enum, if public, is part of you software interface. Interfaces, which have been around a long time before Java and C# coined the expression, are any contract between the client and the called code. Right? And as such are subject to the Open-Closed principle.
Sure. And that (logically) has *nothing* to do with how the source code
is laid out, because the source code is not part of the public
interface. The values of the enums are, but they don't have to be
determined by the order they appear in the source code - that only
happens when you let the compiler assign the values. But, that's a basic design fundamental anyway. Based on the Open-Closed principle. This does not matter whether you are talking about a class, a COM object, or in this case, an Enum. It is a public interface and cannot be modified. It can only be extended.
Sure. I don't believe that the source code forms part of the interface though.
Any part of the contract is part of the interface. If you supply a type, Enum, or other portions of code as public, you are supplying them to fufill the contract. If you change the enum that your method takes, you fundamentally have changed that contract. If the client of that code uses a method that takes the same arguments, including the Enum you changed, then did the method change, or is it the same? What if the method now does not throw (or return an error, or null :) like it used to because a value has been added to the Enum. But, the client code expects that to be an error. That could be a bug. And one that is hard to detect, because there is no error now. It was a contract, and the the contract was broken.
I don't think adding values to enums breaks the contract - in my view,
the contract is in terms of not removing things. In the same way, I
don't mind MS adding extra methods to BCL types, but I'd mind if they
removed them. I would simply map the status code to the name and vice-versa.
So you'd use a separate map? That seems a bit of a waste to me.
Has worked very well for me in the few places where I actually need it. And its not a data map, but a mapping class.
I'm sure it's worked, but that doesn't necessarily mean it was the best
way of doing things. Hang on though - a minute ago you were accusing me of breaking things by changing numbers (which I wasn't). Now you're suggesting that the "specific implementation" of the enum (by which I assume you mean the values) shouldn't be relied upon?
This is the very point I have been suggesting all along. The code should not use explicit values of an Enum. (Except the case as aformentioned when you are using a bit flag, or other compelling reason.)
The code *using* the enum just uses the name - but the enum itself is
responsible for mapping from external integral values to the enum value
as referenced by other code. Whereas the way I'd do it, you'd still only have one place to change them for conversion (not that they should be changed, as we've agreed above) - but that place would also be the definition of the enum. You'd have one piece of source code doing both jobs, which I believe is more compact. If an extra code is needed, you only need to add it in one place rather than two.
I think we agree on this. But, are you saying that you too do not use the value of the Enum after it is assigned?
Very rarely.
So, you are only using the value as a means of reading to/from the external or other system that required you to set them to that value to begin with? Because this is the main part of my suggestion. I prefer not to assign them or assume anything about their value (except the bit flag or other compelling case) and use a mapping class to set them. And from what I think you are saying, this is basically the same, except you use the actual Enum as you mapping. ???
Sounds like it.
The only difference, this being the case, is the choice of mapping technique.
Yup - in my case, I only have one place to look, I can add extra things
to the enums without worrying about location, and if I ever *do* use
the value (eg by printing it out somewhere) then it'll be the same
value as the external system uses.
Why add an unnecessary layer of redirection? Not necessarily. In particular, if you assume that and you use the MS HttpStatusCode enumeration, you may find that a webserver has given you a value you don't understand. If the value is coming from outside your control, you *should* be defensive about whether or not it's one that you understand. You don't need to use a map to do that though.
I don't know how this would have anything to do with the code in the Enum. Sure, I would be defensive that I only understand values in the enumeration. And perhaps, only a subset of those. But I would not assume that, for example, the HttpStatusCode.OK necessarily equals 200, even though that may have been the actual code sent back. I would not compare my enum against a value of 200. I would have no need to do this. I would check against the enum name.
As you said, you would be defensive that you only understand the values
in the enumeration - which completely blows out of the water your
problem with not having a value of 0 in the enumeration. You're the one claiming the value should have no signficance, as I understand it. I'm saying that the value should have the same significance inside the code as in the external system, for the sake of clarity and maintenance. If you get passed a value you don't understand from the external system, you should react appropriately (whatever that reaction is for the situation.)
Yes, I am claiming that the value has no significance, or at least should have not significance. But you said you could just change your value to start at zero. If it does not matter if its zero or twelve, then what does it matter at all?
It matters if it's easier to write and read the code when there are
fewer layers of indirection.
And I am claiming that you must make sure that you correctly take a system that for example passes an int 200 as the return of a status code for and http service, and map it to HttpStatusCode.OK (assuming that is how you would like to use it internally). And then, from there on, who cares if it was status code 200, 501, 400, etc.? Its a HttpStatusCode.OK. Isn't that enough? Why would I need to know its internal representation?
In the case of HttpStatusCode, you can assume that the codes *do* map
directly onto the status codes from the relevant RFC, as that's what
the documentation describes.
Why would I write more code (which could have bugs in) when the
documentation guarantees that I can just cast to the enum?
--
Jon Skeet - <sk***@pobox.com> http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Jon wrote: Frisky <Fr***********@NorthPole.net> wrote: I think we agree on this. But, are you saying that you too do not use the value of the Enum after it is assigned?
Very rarely.
Sometimes only the enum itself is sufficient, and sometimes its not.
It really is Application depended.
For example,
enum BaudRates : int
{
BAUD_300 = 300,
BAUD_2400 = 2400,
BAUD_4800 = 4800,
BAUD_9600 = 9600
...
}
if you only need the enum, to represent the mode and not initialize
anything, so only the enum is, as I said, sufficient but if you need to
initialize, a DCB (a struct which is used in serial port
configuration), then you need to cast the enum into value.
Cheers,
Eyal. This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
by: Rob Jackson |
last post by:
HiI've got a struct, known by file A.c, which contains a pointer to
struct B. Struct B is unknown by file A.c (it is declared in C.h), and
contains a typedef enum, which is declared in a file B.h,...
|
by: Matt |
last post by:
Hi,
Recently we had some code like this cause a failure:
MyEnum myEnum = (MyEnum) (int) dt;
i.e. reading an int out of the database and casting it into a
type-safe enum.
The thought...
|
by: babylon |
last post by:
I have an enum
public enum MyEnum : int
{
X,
Y
}
I have to do
int a = (int) MyEnum.X;
can i overload the operator or other means to do something like
|
by: DKode |
last post by:
I started using Enums to make my code more readable. Here is my ENUM:
public enum EntryType : int {
RegularHours = 1,
Lunch = 2,
Vacation = 3,
Sick = 4,
Personal = 5
}
|
by: Remco |
last post by:
Hi,
Let me try to simply explain my questions.
I've created a portal site with different types of users, e.g. Portal
Administrators and Normal Users.
One base class SessionUser (has a enum...
|
by: Greg |
last post by:
Not sure if this is best place for this problem, but here it is. I have a
project that is simply a C# class that interfaces with an IFilter. This is
so I can retreive the text from Word docs. ...
|
by: kc |
last post by:
I'm trying to pull data from a database that I have no control over the
structure of. There's a members table with a column for the member's
sex. It just stores the sex as M or F. I'd like to...
|
by: NullQwerty |
last post by:
Hey folks,
So, I've got three enum types:
enum enum1
enum enum2
enum enum3
And then I've got a function overloaded three times to accept each
enum type:
private void func(enum1 myenum){}
|
by: mitdej |
last post by:
Hi there,
I have an several enum types that starts from a nunmber other than 0.
For example:
public enum InternalStatus
{
Pending = 1,
Ported = 2,
Suspended = 3
}
I put this values in a int...
|
by: Rene |
last post by:
If variance/covariance is not allowed in array of value types, why is the
expression on the "Main" method run successfully (see snippet below)? I am
missing something?
Thank you.
...
|
by: lllomh |
last post by:
Define the method first
this.state = {
buttonBackgroundColor: 'green',
isBlinking: false, // A new status is added to identify whether the button is blinking or not
}
autoStart=()=>{
|
by: DJRhino |
last post by:
Was curious if anyone else was having this same issue or not....
I was just Up/Down graded to windows 11 and now my access combo boxes are not acting right. With win 10 I could start typing...
|
by: Aliciasmith |
last post by:
In an age dominated by smartphones, having a mobile app for your business is no longer an option; it's a necessity. Whether you're a startup or an established enterprise, finding the right mobile app...
|
by: NeoPa |
last post by:
Hello everyone.
I find myself stuck trying to find the VBA way to get Access to create a PDF of the currently-selected (and open) object (Form or Report).
I know it can be done by selecting :...
|
by: Teri B |
last post by:
Hi, I have created a sub-form Roles. In my course form the user selects the roles assigned to the course.
0ne-to-many. One course many roles.
Then I created a report based on the Course form and...
|
by: isladogs |
last post by:
The next Access Europe meeting will be on Wednesday 1 Nov 2023 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM)
Please note that the UK and Europe revert to winter time on...
|
by: nia12 |
last post by:
Hi there,
I am very new to Access so apologies if any of this is obvious/not clear.
I am creating a data collection tool for health care employees to complete. It consists of a number of...
|
by: NeoPa |
last post by:
Introduction
For this article I'll be focusing on the Report (clsReport) class. This simply handles making the calling Form invisible until all of the Reports opened by it have been closed, when it...
|
by: GKJR |
last post by:
Does anyone have a recommendation to build a standalone application to replace an Access database? I have my bookkeeping software I developed in Access that I would like to make available to other...
| |