232

In C#, is it possible to decorate an Enum type with an attribute or do something else to specify what the default value should be, without having the change the values? The numbers required might be set in stone for whatever reason, and it'd be handy to still have control over the default.

enum Orientation
{
    None = -1,
    North = 0,
    East = 1,
    South = 2,
    West = 3
}

Orientation o; // Is 'North' by default.
xyz
  • 27,223
  • 29
  • 105
  • 125
  • Should you be able to change the default value for int?, double?, etc.? – A.R. Dec 13 '14 at 05:45
  • 4
    @A.R. No offense to past you, but it doesn't make sense to compare enums to `int`s *in the abstract*, simply because they happen to be implemented as a numeric types. We could implement enums as strings, and it would not change their usefulness. I consider the answer here a limitation of the expressiveness of the C# language; the limitation is certainly not inherent in the idea of "distinguishing values from a restricted set." – jpaugh May 21 '18 at 19:11
  • 1
    @jpaugh I'm not comparing enums to ints "in the abstract". I'm giving examples of other data (including strings and other reference) types where changing the defaults makes no sense. It's not a limitation, it is a design feature. Consistency is your friend :) – A.R. May 22 '18 at 20:50
  • @A.R. Point taken. I suppose I spend too much time thinking of `enum`s as type-level constructs, specifically as [*sum types*](https://chadaustin.me/2015/07/sum-types/) (or [see here](https://en.wikipedia.org/wiki/Sum_type). That is, consider each enum as a distinct type, where all values of that type are distinct from every other enum's values. From such a mindset, it is impossible for enums to share *any* value, and indeed, this abstraction falls apart when you consider that the default of `0` may or may not be valid for a given enum, and is simply shoe-horned into every enum. – jpaugh May 22 '18 at 21:19
  • Yes, I am familiar with discriminated unions. C# Enums aren't that, so I don't know if it is helpful to think of them at such a high (and incorrect) level. While a 'sum type' certainly has its advantages, so does and enum (assuming appropriate values are provided). e.g. myColor = Colors.Red | Colors.Blue. My main point is that if you want a sum type for c#, make one, rather than trying to repurpose the concept of an enum. – A.R. May 23 '18 at 14:44

14 Answers14

386

The default for an enum (in fact, any value type) is 0 -- even if that is not a valid value for that enum. It cannot be changed.

Yair Nevet
  • 12,725
  • 14
  • 66
  • 108
James Curran
  • 101,701
  • 37
  • 181
  • 258
  • 14
    Rephrase the question to ask that the default value for an int be 42. Think how daft that sounds... Memory is *blanked* by the runtime before you get it, enums are structs remember – ShuggyCoUk Feb 10 '09 at 10:15
  • 3
    @DougS 1. No, but admitting you were wrong is. 2. He didn't earn any reputation from comment upvotes. – Aske B. Nov 23 '12 at 13:01
  • 7
    The comments made me suspicious about this answer, so I tested it and verified that this answer definitely is correct. – Ian Newson Jan 29 '13 at 10:12
  • 1
    @JamesCurran 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:55
  • So what happens if a variable of type `MyEnum { SingleMember = 10 }` defaults to zero? The answer is nothing. C# has no problem with `MyEnum e` having a value of zero even though the enumeration doesn't define it. It just doesn't have a name associated with it. – xr280xr Apr 06 '22 at 19:55
70

The default value of any enum is zero. So if you want to set one enumerator to be the default value, then set that one to zero and all other enumerators to non-zero (the first enumerator to have the value zero will be the default value for that enum if there are several enumerators with the value zero).

enum Orientation
{
    None = 0, //default value since it has the value '0'
    North = 1,
    East = 2,
    South = 3,
    West = 4
}

Orientation o; // initialized to 'None'

If your enumerators don't need explicit values, then just make sure the first enumerator is the one you want to be the default enumerator since "By default, the first enumerator has the value 0, and the value of each successive enumerator is increased by 1." (C# reference)

enum Orientation
{
    None, //default value since it is the first enumerator
    North,
    East,
    South,
    West
}

Orientation o; // initialized to 'None'
Emperor XLII
  • 13,014
  • 11
  • 65
  • 75
50

If zero doesn't work as the proper default value, you can use the component model to define a workaround for the enum:

[DefaultValue(None)]
public enum Orientation
{
     None = -1,
     North = 0,
     East = 1,
     South = 2,
     West = 3
 }

public static class Utilities
{
    public static TEnum GetDefaultValue<TEnum>() where TEnum : struct
    {
        Type t = typeof(TEnum);
        DefaultValueAttribute[] attributes = (DefaultValueAttribute[])t.GetCustomAttributes(typeof(DefaultValueAttribute), false);
        if (attributes != null &&
            attributes.Length > 0)
        {
            return (TEnum)attributes[0].Value;
        }
        else
        {
            return default(TEnum);
        }
    }
}

and then you can call:

Orientation o = Utilities.GetDefaultValue<Orientation>();
System.Diagnostics.Debug.Print(o.ToString());

Note: you will need to include the following line at the top of the file:

using System.ComponentModel;

This does not change the actual C# language default value of the enum, but gives a way to indicate (and get) the desired default value.

David
  • 1,743
  • 1
  • 18
  • 25
  • sorry it doesn't work for you. Can you add more info? you need to add the line using System.ComponentModel; and then write the GetDefaultEnum() function in a Utilities class. What version of .net are you using? – David Oct 23 '12 at 18:27
  • 3
    +1 for the reuse of the component model attribute and the clean solution. I'd like to recommend you to change the last line in the `else` statement as follows: `return default(TEnum);`. Fist, it will reduce the slower `Enum.GetValues(...).***` calls, second (and more important) it will be generic for any type, even non-enums. Besides, you do not restrict the code to be used for enums only, so this will actually fix potential exceptions when used over non-enum types. – Ivaylo Slavov Dec 03 '13 at 17:37
  • 1
    This may be a misuse of the default value attribute in the context of the question asked. The question asked is about the automatically initialized value, which won't change with the proposed solution. This attribute is meant for a visual designer's default differing from the initial value. There is no mention by the person asking the question of visual designer. – David Burg Dec 01 '16 at 17:29
  • 2
    There really is nothing in MSDN documentation that the ComponentModel or DefaultAttribute is a "visual designer" only feature. As the accepted answer states. The short answer is "no, its impossible" to redefine the default value of an enum to something other than the 0 value. This answer is a workaround. – David Dec 08 '16 at 15:22
17

An enum's default is whatever enumeration equates to zero. I don't believe this is changeable by attribute or other means.

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

Joe
  • 41,484
  • 20
  • 104
  • 125
15

One more way that might be helpful - to use some kind of "alias". For example:

public enum Status
{
    New = 10,
    Old = 20,
    Actual = 30,

    // Use Status.Default to specify default status in your code. 
    Default = New 
}
Dmitry Pavlov
  • 30,789
  • 8
  • 97
  • 121
  • 2
    The suggestion is good, however, as mentioned already in other answers, enumerations have their default value to be zero. In your case, the expression `Status s = default(Status);` will not be any of the status members, as `s` it will have the value of `(Staus) 0`. The latter is valid to write directly, as enums can be cast to integers, but it will fail during deserialization, as the framework makes sure that an enum is always deserialized to a valid member. Your code will be perfectly valid if you change the line `New = 10` to `New = 0`. – Ivaylo Slavov Dec 03 '13 at 17:49
  • 2
    Yes. New = 0 would work. I would personally avoid not setting enum members explicitly. – Dmitry Pavlov Dec 04 '13 at 11:57
11

You can't, but if you want, you can do some trick. :)

    public struct Orientation
    {
        ...
        public static Orientation None = -1;
        public static Orientation North = 0;
        public static Orientation East = 1;
        public static Orientation South = 2;
        public static Orientation West = 3;
    }

usage of this struct as simple enum.
where you can create p.a == Orientation.East (or any value that you want) by default
to use the trick itself, you need to convert from int by code.
there the implementation:

        #region ConvertingToEnum
        private int val;
        static Dictionary<int, string> dict = null;

        public Orientation(int val)
        {
            this.val = val;
        }

        public static implicit operator Orientation(int value)
        {
            return new Orientation(value - 1);
        }

        public static bool operator ==(Orientation a, Orientation b)
        {
            return a.val == b.val;
        }

        public static bool operator !=(Orientation a, Orientation b)
        {
            return a.val != b.val;
        }

        public override string ToString()
        {
            if (dict == null)
                InitializeDict();
            if (dict.ContainsKey(val))
                return dict[val];
            return val.ToString();
        }

        private void InitializeDict()
        {
            dict = new Dictionary<int, string>();
            foreach (var fields in GetType().GetFields(BindingFlags.Public | BindingFlags.Static))
            {
                dict.Add(((Orientation)fields.GetValue(null)).val, fields.Name);
            }
        } 
        #endregion
Avram
  • 4,267
  • 33
  • 40
  • In your implicit conversion operator you need `value + 1`, otherwise now your `default(Orientation)` returns `East`. Also, make the constructor private. Good approach. – nawfal Jun 10 '15 at 20:53
7

Actually an enum's default is the first element in the enum whose value is 0.

So for example:

public enum Animals
{
    Cat,
    Dog,
    Pony = 0,
}
//its value will actually be Cat not Pony unless you assign a non zero value to Cat.
Animals animal;
Meneer Venus
  • 1,039
  • 2
  • 12
  • 28
Cian
  • 103
  • 1
  • 1
  • 10
    However, in that case "Pony" IS "Cat" (e.g, `Console.WriteLine(Animals.Pony);` prints "Cat") – James Curran Dec 08 '10 at 18:33
  • 17
    Actually you should either: never specify any value OR specify all values OR only specify the value of the first defined member. Here what happens is that: Cat has no value and it's the 1st value, so automatically sets it to 0. Dog has no value, automatically sets it to PreviousValue + 1 ie 1. Poney has a value, leave the value. So Cat = Pony = 0, Dog = 1. If you have {Cat, Dog, Pony = 0, Frog} then Dog = Frog = 1. – user276648 Sep 14 '11 at 07:30
4

The default value of enum is the enummember equal to 0 or the first element(if value is not specified) ... But i have faced critical problems using enum in my projects and overcome by doing something below ... How ever my need was related to class level ...

    class CDDtype
    {
        public int Id { get; set; }
        public DDType DDType { get; set; }

        public CDDtype()
        {
            DDType = DDType.None;
        }
    }    


    [DefaultValue(None)]
    public enum DDType
    {       
        None = -1,       
        ON = 0,       
        FC = 1,       
        NC = 2,       
        CC = 3
    }

and get expected result

    CDDtype d1= new CDDtype();
    CDDtype d2 = new CDDtype { Id = 50 };

    Console.Write(d1.DDType);//None
    Console.Write(d2.DDType);//None

Now what if value is coming from DB .... Ok in this scenario... pass value in below function and it will convertthe value to enum ...below function handled various scenario and it's generic... and believe me it is very fast ..... :)

    public static T ToEnum<T>(this object value)
    {
        //Checking value is null or DBNull
        if (!value.IsNull())
        {
            return (T)Enum.Parse(typeof(T), value.ToStringX());
        }

        //Returanable object
        object ValueToReturn = null;

        //First checking whether any 'DefaultValueAttribute' is present or not
        var DefaultAtt = (from a in typeof(T).CustomAttributes
                          where a.AttributeType == typeof(DefaultValueAttribute)
                          select a).FirstOrNull();

        //If DefaultAttributeValue is present
        if ((!DefaultAtt.IsNull()) && (DefaultAtt.ConstructorArguments.Count == 1))
        {
            ValueToReturn = DefaultAtt.ConstructorArguments[0].Value;
        }

        //If still no value found
        if (ValueToReturn.IsNull())
        {
            //Trying to get the very first property of that enum
            Array Values = Enum.GetValues(typeof(T));

            //getting very first member of this enum
            if (Values.Length > 0)
            {
                ValueToReturn = Values.GetValue(0);
            }
        }

        //If any result found
        if (!ValueToReturn.IsNull())
        {
            return (T)Enum.Parse(typeof(T), ValueToReturn.ToStringX());
        }

        return default(T);
    }
Moumit
  • 8,314
  • 9
  • 55
  • 59
  • -1 for intentionally not answering the given question. This is not an obvious homework problem, which should be the only case in which you intentionally don't answer. – Xynariz Feb 11 '14 at 21:21
  • 1
    @Xynariz .. sorry guys.. my comments was negative mistakely because my real intention was to provide a solution in other way... So i changed my comments ... :D – Moumit Mar 26 '14 at 14:16
3

The default value for an enumeration type is 0:

  • "By default, the first enumerator has the value 0, and the value of each successive enumerator is increased by 1."

  • "The value type enum has the value produced by the expression (E)0, where E is the enum identifier."

You can check the documentation for C# enum here, and the documentation for C# default values table here.

acoelhosantos
  • 1,549
  • 14
  • 19
2

If you define the Default enum as the enum with the smallest value you can use this:

public enum MyEnum { His = -1, Hers = -2, Mine = -4, Theirs = -3 }

var firstEnum = ((MyEnum[])Enum.GetValues(typeof(MyEnum)))[0];

firstEnum == Mine.

This doesn't assume that the enum has a zero value.

Tal Segal
  • 2,735
  • 3
  • 21
  • 17
2
enum Orientations
{
    None, North, East, South, West
}
private Orientations? _orientation { get; set; }

public Orientations? Orientation
{
    get
    {
        return _orientation ?? Orientations.None;
    }
    set
    {
        _orientation = value;
    }
}

If you set the property to null will return Orientations.None on get. The property _orientation is null by default.

0

Don't rely on the enum value in this case. Let None be 0 as a default.

// Remove all the values from the enum
enum Orientation
{
    None, // = 0 Putting None as the first enum value will make it the default
    North, // = 1
    East, // = 2
    South, // = 3
    West // = 4
}

Then use a method to get the Magic Number. You can introduce an Extension Method and use it like:

// Extension Methods are added by adding a using to the namespace
using ProjectName.Extensions;

Orientation.North.ToMagicNumber();

And here is the code:

namespace ProjectName.Extensions
{
    public static class OrientationExtensions 
    {
        public static int ToMagicNumber(this Orientation orientation) => oritentation switch
        {
            case None  => -1,
            case North => 0,
            case East  => 1,
            case South => 2,
            case West  => 3,
            _          => throw new ArgumentOutOfRangeException(nameof(orientation), $"Not expected orientation value: {orientation}")
        };
    }
}
Redwolf
  • 540
  • 4
  • 17
0

The default is the first one in the definition. For example:

public enum MyEnum{His,Hers,Mine,Theirs}

Enum.GetValues(typeOf(MyEnum)).GetValue(0);

This will return His

Ryan Kohn
  • 13,079
  • 14
  • 56
  • 81
Tony Hopkinson
  • 20,172
  • 3
  • 31
  • 39
  • haha; the "default value" is zero. BUT! he says, the default value "zero" only happens to be the default symbol of the first named value; ! so in other words the language choose the default instead of you; this also just happens that zero is default value of an int.. lol – user1953264 Jun 15 '19 at 00:01
-5
[DefaultValue(None)]
public enum Orientation
{
    None = -1,
    North = 0,
    East = 1,
    South = 2,
    West = 3
}

Then in the code you can use

public Orientation GetDefaultOrientation()
{
   return default(Orientation);
} 
  • 14
    /!\ WRONG /!\ The DefaultValueAttribute doesn't actually set the value, it's just for information purposes only. Then it's up to you to check whether your enum, field, property, ... has that attribute. The PropertyGrid uses it so that you can right click and select "Reset", also if you're not using the default value the text is shown in bold - BUT - you still have to manually set your property to the default value you want. – user276648 Sep 14 '11 at 07:21