19

What's the point of having '0' as a default value for enum in C#? If I declare enumeration that starts with a different number:

enum Color
{
   Blue = 1,
   Green,
   Red,
}

then var color = default(Color) - will return me '0'. I expected to see the minimum value instead. This behavior may cause problems if each member of the enumeration corresponds to some specific number and '0' is not a valid value.

username
  • 3,378
  • 5
  • 44
  • 75
  • 2
    Why a "minimum value"? Why not have enums that count down? – BoltClock May 24 '12 at 17:30
  • 2
    Why would you start the values at anything other than 0? Most programmers are accustomed to using 0 as a starting point when counting, e.g. like when working with arrays. I would suggest not even giving your enums values unless you have a really good reason to do so. – Jesse Webb May 24 '12 at 17:48
  • @JesseWebb This is an example. But I could declare enumeration, where each member holds some specific value. Recently I worked with files of a certain format, where each entry were defined by 1, 2 or 3 tag values. – username May 24 '12 at 17:58
  • @JesseWebb sometimes compatibility with external processes makes it easier to map explicit numerical values of the external process to human-redable handles inside the .net application. If you deal with a legacy system that returns values between 8 and 27 (because 0..7 have been deprecated 8 years ago), it can be easier to map those values numerically to enum values. (Though yes, in the general case this shouldn't happen.) – Cornelius Sep 17 '14 at 13:38

8 Answers8

14

Default value for all value types (including enum) is bitwise 0. As result it means that 0 is always possible value for enum even if it is not explicitly defined.

Here is the specification: Default values table

EDIT: for more details check MSDN for enumeration types - enum

enum is type which is special in a way the it sort-of derives from other value type (which normally not possible), but behaves as value type of its backing type. An enum can use only some integral values as backing type.

Note: as @archil points out enum value may contain any value of backing type, irrespective of list of constants enumerated in enum itself. For enums marked with "FlagsAttribute" this behavior is normally expected, but for normal enums it may not be intuitive.

Alexei Levenkov
  • 98,904
  • 14
  • 127
  • 179
  • 1
    I've read the doc thanks, but the question is why so. Isn't enumeration supposed to hold only values that are declared in code? Now I have to create default 0 element and always check that it is not that element. And I can't safely expect that enum member is always the one I provided. I suppose it was easy to implement it this way in C#. – username May 24 '12 at 17:43
  • 1
    No. An enum can contain any value as its backing type (int by default). For the same reason it has the default value as the backing type unless specified otherwise. Use the Enum.IsDefined(value) function to validate input enum parameters. – Dmitry S. May 24 '12 at 17:47
  • 1
    Hmm, I should have read this answer before posting my own. However, this one's a little too generalized: enums aren't value types, but their backing types are. An enum cannot use *any* value as its backing type, only integral values. It's worth clarifying these points. :) – Dan J May 24 '12 at 17:53
  • @DanJ, actually, an enum is a ValueType. Check its inheritance chain. – Keith Robertson May 24 '12 at 18:06
  • Thanks @DanJ, Added to the answer. +1 to your and archil answers for good points. – Alexei Levenkov May 24 '12 at 18:10
  • IMO, this defeats the "use case" of enumerations -- limiting types to only what you define in a list. Sigh. "Works as designed" – ashes999 Mar 15 '13 at 16:21
  • _"Default value for all value types (including enum) is bitwise 0"_ `DateTime` is a `struct`, so also a value-type, but it's default value is `DateTime.MinValue`. – Tim Schmelter Oct 26 '15 at 12:08
  • @TimSchmelter "but"? `DateTime.MinValue` is bitwise 0 - not sure how one is opposite to another. – Alexei Levenkov Oct 26 '15 at 17:03
10

We can only conjecture about why an aspect of the .NET framework was designed a certain way. For the most straightforward explanation, I'd like to highlight this remark from the MSDN documentation:

An enumeration is a set of named constants whose underlying type is any integral type except Char. If no underlying type is explicitly declared, Int32 is used.

Note that a .NET enumeration is essentially an extension of an integral type. The default value for integral types is 0, so it's reasonable (if somewhat inconvenient in the cases you've illustrated) for enumerations to inherit that behaviour.

Dan J
  • 16,319
  • 7
  • 50
  • 82
  • But when not using 0 values for enums I encounter "An exception of type 'System.NullReferenceException' occurred in MyProjectName.dll but was not handled in user code. Additional information: Object reference not set to an instance of an object." error. How to fix it? Note: I use an extension method in order to display enum's Descriptions, but not sure how to avoid the error in the helper method (GetDescription) defined on [this page](http://stackoverflow.com/questions/34293468/cannot-display-enum-values-on-kendo-grid/34294589?noredirect=1#comment56355782_34294589) – Jack Dec 16 '15 at 16:54
  • 1
    @Christof I can't answer that question without seeing your code, but the exception you're describing suggests a variable is set to `null` unexpectedly. That's what to look for while debugging. – Dan J Dec 16 '15 at 18:24
  • Ok, thanks. I solved the problem by using the GetDescription() method on [Enum ToString with user friendly strings](http://stackoverflow.com/questions/479410/enum-tostring-with-user-friendly-strings). – Jack Dec 16 '15 at 18:32
7

There always is possibility for enum to have non-existent value. That is why Enum.IsDefined Method exists.

The default value of an enum E is the value produced by the expression (E)0.

archil
  • 39,013
  • 7
  • 65
  • 82
3

As has been stated in multiple answers so far, the "default" value for any fixed-size data structure is 0. The size of the structures memory is set to zero and that is considered "default". Now, if you want to define your own "default" value for an enum, you have multiple options. The easiest would be to write your own function to give you a "minimum valid enum"

private E GetDefaultEnum<E>()
{
    return (E)(Enum.GetValues(typeof(E)).Cast<E>().Min<E>());
}

Usage:

enum Color
{
   Blue = 1,
   Green,
   Red,
}

Color defaultColor = GetDefaultEnum<Color>();
MessageBox.Show(defaultColor.ToString()); // "Blue"

You can obviously alter how you determine a "default" value, but this way seems best suited to your needs.

Jason Larke
  • 5,289
  • 25
  • 28
1

Why is 0 the default enum value? Ease of runtime implementation. The default of any value type is bitwise 0, and presumably a null reference is represented by bitwise 0. Thus to initially construct an object with its default values, we only need to know its size; the runtime doesn't need to know or process anything about the object's structure. Similarly, the pre-defined value-type constructor can merely fill a memory range with zeroes.

Like it or not, that's how it is. What we need to do in response is when designing an enum, whatever name is a suitable default, give it the value 0. If there is no suitable default, then your methods accepting such an enum as a parameter might check that it's properly set, e.g.

void ProcessColor(Color c) {
    if (c == 0)
        throw new ArgumentException("Color is not set", "c");
    //...
}
Keith Robertson
  • 791
  • 7
  • 13
  • Yeah, that's what I have to do now, to check whether it's not 0. But anyway it's better to include a default value of 0 in enum to avoid any implicit inconsistencies. Thank you. – username May 24 '12 at 18:26
0

The point is probabbly is in having less positive integer possible value.

Why less positive?

To be able to treat enum with bit-shift operation correctly.

I'm naturally talking about default value, that can be changed by developer.

Tigran
  • 61,654
  • 8
  • 86
  • 123
0

I am not sure why but...

Here is the doc about C# enum: http://msdn.microsoft.com/en-us/library/sbbt4032.aspx

Enumerators can use initializers to override the default values, as shown in the following example.

enum Days {Sat=1, Sun, Mon, Tue, Wed, Thu, Fri};

In this enumeration, the sequence of elements is forced to start from 1 instead of 0. However, including a constant that has the value of 0 is recommended. For more information, see Enumeration Types (C# Programming Guide).

They recommend you always include a placeholder enum value which corresponds to the value 0 otherwise you may run into problems. You could name this enum value something like Undefined or Default or something like that.

As I mentioned in my comment to your question though, my recomendation would be to not use values for your enums at all unless you have a very good reason for doing so. If you need to, follow the MSDN Programming Guide for Enumeration Types

Jesse Webb
  • 43,135
  • 27
  • 106
  • 143
0

enum is int (by default). Enums are human-readable ints for our source code, but when your program gets compiled, there is no enum, only ints. The default value for int is 0.

This code:

public enum test { One, Two, Three }

var x = test.One;
var y = 0;

Becomes this in IL:

IL_0001:  ldc.i4.0   
IL_0002:  stloc.0     
IL_0003:  ldc.i4.0    
IL_0004:  stloc.1 

So, how could an int have a default value of 1 (as you ask) in some cases, but not others?

mafue
  • 1,858
  • 1
  • 21
  • 27