Why enumeration of transfers is allowed, even if the transfer does not have a valid value

When reading Jon Skeet, answer this specific question. How can I do this so that my class variables can only be set to one of three options? I learned something new that I did not know about in C #, and I assume the CLR system is type.

What is the reason for this legal:

public enum Tests { Zero = 0, One, Two } var nonExistantTestsValue = (Tests)1000; 

It will be perfectly composed, but I see no reason why this is so. The whole point of the enumerations, as far as I can see, is to limit a certain number of options to the value of a given variable of a specified type.

If the restriction imposed by the enum definition breaks so easily, what is the point (besides the readability problem)? Obviously, you can make sure that this is the correct value using reflection, but why is this not done at compile time?

There is probably a good reason why it works as if it is happening, but I do not see it.

+4
source share
5 answers

Any value is allowed because you can mark the enumeration with the Flags attribute. This means that you can compose any value by OR-ing the various members of the enumeration itself. Basically, the compiler is not smart enough to take care of any possible way to use an enumeration.

EDIT: found Eric Lippert's previous post:

Why does casting an int for an invalid enum value DO NOT throw an exception?

+1
source

Enumerations are essentially unique types that allow you to assign symbolic names to integer values. They are not used to limit the valid values ​​of a variable ...

+5
source

If the restriction imposed by the definition of an enumeration breaks so easily, what is the point

I think that the abstraction of the enumeration was not designed with limitations or warranties in mind. I think it was designed with convenience and support in mind.

Good reasons:

Skip the first bullet if you do not want to see simple truths <Sub> right now

  • language specification [the reason I mention is to remind people of the limited use of debating facts; a phrase like ... then what the point calls this for me]

sub>

  • (It’s hard / impossible to say when validation was not needed, and this would make performance difficult for certain applications.

(Remember that CLR functions can be called from anywhere, not just from C #, not just from your assembly)

+3
source

More questions are what you can do when enums are not limited to values:

Flags are one of the following examples:

 [Flags] enum MyFlag { a, b, c } 

Now you can execute the bit:

 MyFlag flags = MyFlag.a|MyFlag.b; 
+2
source

I do not know the reasons for this design decision, but we can look at some of its consequences.

Take a look at the IL enumeration view:

 .class private auto ansi sealed MyEnum extends [mscorlib]System.Enum { // Fields .field public specialname rtspecialname int32 value__ .field public static literal valuetype MyEnum Value0 = int32(0) .field public static literal valuetype MyEnum Value1 = int32(1) .field public static literal valuetype MyEnum Value2 = int32(2) } 

First, note that this is a value type and therefore (MyEnum)0 must be valid. Secondly, we see that the possible values ​​of the enumerations are just const and that the enumerations at the run level are assignments compatible with whole literals.

Continuum constants usually become whole letters. Therefore, if you want to prevent the occurrence of invalid enumerations, you will need to enter either expensive runtime checks when converting from an enumeration, or non-trivial cross-assembly time checks to make sure that enumeration literals baked in another assembly are valid.


Another thing is that you can create enumerations supported by long ones. But one property of longitude is that their purpose is not guaranteed to be atomic. Thus, ensuring that the value of en long is enumerated is difficult.

 enum MyLongEnum:long { Value1=0x0101010102020202, Value2=0x0303030304040404 } 

If you have assigned such an enumeration from multiple threads, you can get a mixed value that is invalid even if you never assigned an invalid value.


There is also an easy workaround for getting safe enumerations: use a private constructor class and static fields or readonly properties for possible values. This way you lose whole conversions, literals, and non-nullability, but you get type safety and better version control.

+1
source

All Articles