39

The following code does not produce an exception but instead passes the value 4 to tst. Can anyone explain the reason behind this?

 public enum testing
 { 
    a = 1,
    b = 2,
    c = 3
 }

testing tst = (testing)(4);
gonzobrains
  • 7,856
  • 14
  • 81
  • 132
Ted Smith
  • 9,415
  • 16
  • 50
  • 52

4 Answers4

59

In C#, unlike Java, enums are not checked. You can have any value of the underlying type. This is why it's pretty important to check your input.

if(!Enum.IsDefined(typeof(MyEnum), value))
     throw new ArgumentOutOfRangeException();
Mehrdad Afshari
  • 414,610
  • 91
  • 852
  • 789
  • 7
    There are some features of C# that I long for as a Java developer (LINQ!), but here Java really got it right ... – Joachim Sauer Mar 06 '09 at 10:35
  • @saua: Not necessarily. They are advantages to this approach, as well as disadvantages. – Mehrdad Afshari Mar 06 '09 at 10:36
  • The main advantage of this point is that you can combine the values, which you should also mark with [Flags] attribute. – Martin C. Mar 06 '09 at 11:02
  • 1
    I know, but I can also do that using an EnumSet, which is less bit-fiddling-like and more OO in my opinion. Generally I simply prefer the Java way where enums are objects in disguise as opposed to ints in disguise. But that's pretty subjective of course. – Joachim Sauer Mar 06 '09 at 20:42
  • 3
    saua: Generally, Java's enums are much more powerful. But in this simple case, .NET reasoning is impeccable: runtime checks for potentially invald flag combinations are time-consuming and completely useless most of the time: you'd pay a lot for a feature you don't use except rarely. – Konrad Rudolph Apr 15 '09 at 11:55
4

Since your enum is based on int, it can accept any value that int can. And since you are telling the compiler explicitly (by casting) that it is ok to cast 4 into your enum it does so.

Alex Reitbort
  • 13,504
  • 1
  • 40
  • 61
1

Each enum has an underlying numeric type (e.g. int) that is used for representation. Even if a value doesn't have a name, it's a possible value the enum can have.

Brian
  • 117,631
  • 17
  • 236
  • 300
1

What others didn't say: With casting, you tell the compiler that you know what you're doing. So if you tell it, treat this as an enum value, it does. The other posters pointed out why this is still allowed, as the C# compiler doesn't allow many bad things, even if you say you know what you're doing.

It would be really bad if the value was not allowed, because then you couldn't save a flag value as an int. Or, someone had to check whether the int is one of the allowed combinations, which can be a lot if you use a flag enum (with values that can be or'ed together).

OregonGhost
  • 23,359
  • 7
  • 71
  • 108
  • I am not sure the second paragraph really applies. That comment is on whether the cast should be allowed or not in the language, but there's the question of what the cast does, whether it should be checked or not. C# has chosen to allow variables for `enum` type to be able to hold any value that the underlying integral type has. An alternative approach would be to check and throw `InvalidCastException` if the value is not representable in the enum. – David Rodríguez - dribeas Oct 22 '18 at 12:35
  • 2
    This happens also with `Enum.Parse` and `Enum.TryParse` methods, so the problem here is not related with casting but instead with a language decision. – Diogo Rocha Dec 11 '20 at 16:16