1

I'm very confused here. Suppose I have two programs in Visual Studios - I'm using C# WPF. Suppose I have two programs where Program 1 has Program 2 as a reference - and similarly Program 2 has Program 1 as a reference.

Program1.sol

p1.xaml.cs contents:

public void checkStuff(myThing x)
{
   // Do stuff (irrelevant)
}

public enum myThing
{
  stuff,
  stuff2,
  stuff3,
  stuff4
}

Program2.sol

p2.xaml.cs contents:

// Let's say I call that function
p1 p1content = new p1();
p1content.checkStuff(0); // <-- Why does this work??

My question is, why does the number 0 work as a parameter? This may be trivial but what exactly does the program think I am passing in that function when I pass in 0? At first I thought it was the index of the variables located in my enum class, but it can't be because I can't pass in 1,2, or 3, etc..

H.B.
  • 166,899
  • 29
  • 327
  • 400
  • 2
    FYI, a `enum` and `enumerator` are very diffrent things in C#. You are talking about enums – Scott Chamberlain May 17 '16 at 15:35
  • I dont think you can have circular references as you describe. – Jamiec May 17 '16 at 15:35
  • Thanks @ScottChamberlain, what do you mean exactly Jamiec –  May 17 '16 at 15:36
  • That's not a duplicate question, but it's related. Enums are integral value types and as such need a default-initialization value, which was naturally chosen to be zero. Since an enum can be default-initialized to zero, the language designers chose to allow any enum to also be explicitly initialized to zero. Hence, you can assign 0 to any enum, but not any other integer (without casting). – Matthew Watson May 17 '16 at 15:39
  • Are you asking why `0` works but other numbers don't or why why `0` works if there's not a defined value in the enum for `0`? – D Stanley May 17 '16 at 15:41
  • "Why does `0` work but other numbers do not?" : http://stackoverflow.com/questions/16960428 – D Stanley May 17 '16 at 15:47
  • 1
    "Why does passing `0` work when I have not defined a value for `0`?" : http://stackoverflow.com/questions/6413804 – D Stanley May 17 '16 at 15:47

2 Answers2

4

When you declare an enum such as the one in your question, what actually happens under the hood(ish) is this:

public enum myThing : int
{
  stuff = 0,
  stuff2 = 1,
  stuff3 = 2,
  stuff4 = 3
}

ie, the default, underlying type of an enum is an int, and the fields are started sequentially from zero.

Strangely, this only works for the zero element, for example this works:

checkStuff(0);

but this will not

checkStuff(1); //error

You would need to be explicit

checkStuff((myThing)1); //cast int to myThing
Jamiec
  • 133,658
  • 13
  • 134
  • 193
  • Where do you see that an implict value of 0 is "added" to the enum? If I do `Enum.IsDefined(typeof(myThing),0)` I get `false` which tells me that it's _not_ defined. – D Stanley May 17 '16 at 15:45
  • Look at the first example here @DStanley: https://msdn.microsoft.com/en-gb/library/sbbt4032.aspx (And the definition states `By default, the first enumerator has the value 0, and the value of each successive enumerator is increased by 1.`) – Jamiec May 17 '16 at 15:52
  • OK I thought you were saying an implicit value of `0` is _added_. I misread the original question; my bad. – D Stanley May 17 '16 at 15:54
3

By default in C# the underlying type of enums are int. See the MSDN documentation.

As mentioned in the comment in this SO post:

The enum keyword is used to declare an enumeration, a distinct type consisting of a set of named constants called the enumerator list. Every enumeration type has an underlying type, which can be any integral type except char.

An enum has an integer-based value as base (int, byte, ulong, etc). The compiler only accepts an assigment of zero to guarantee an variable of an enum-based type to be initialized even when no explicit value has been assigned to the enum attributes. The compiler however does not accept any other values. This is a build-in safety, but more so a compromise of addressing a flaw in the compiler design to resolve previous inconsistent behavior with enums. This little story by Eric Lippert provides an insight into how this came into existence.

Community
  • 1
  • 1
Wicher Visser
  • 1,513
  • 12
  • 21
  • 2
    So what? Then why can't i pass in another integer number besides 0? –  May 17 '16 at 15:36
  • @Shammy: You could cast those values (`(myThing)3`). I think the existence of the zeroth element is guaranteed, the others are not. – H.B. May 17 '16 at 15:37
  • You can, you just don't know what the system set them to. You could manually set them if you did want to pass numbers in or print them out to check what numbers the system did assign. 0 is only assigned to the first value, after that, you'd need to check the documentation – Draken May 17 '16 at 15:37
  • 1
    You CANNOT pass any other integer than zero to a method expecting an enum, without casting. But you CAN pass zero without casting. This answer doesn't address the OP's question. – Matthew Watson May 17 '16 at 15:41
  • THANK YOU MATTHEW! @MatthewWatson –  May 17 '16 at 15:42
  • It's just weird, like WHY would that be considered a "safety" Lol –  May 17 '16 at 16:01
  • Here is explained why: https://blogs.msdn.microsoft.com/ericlippert/2006/03/29/the-root-of-all-evil-part-two/ – Wicher Visser May 18 '16 at 07:38