79

If I have a class with an enum member and I want to be able to represent situations where this member is not defined, which is it better?

a) Declare the member as nullable in the class using nullable types. E.g.:

public SomeEnum? myEnum;

b) Add a default, 'unknown' value to the enumeration. E.g.:

public enum SomeEnum {
    Unknown,
    SomeValueA,
    SomeValueB,
    SomeValueC,
}

I can't really see any major pros/cons either way; but perhaps one is preferable over the other?

Pooven
  • 1,744
  • 1
  • 25
  • 44
UpTheCreek
  • 31,444
  • 34
  • 152
  • 221

6 Answers6

72

Definitely use a nullable value type - that's what they're for. It explicitly states your intention. It also means you can use Enum.IsDefined (or the equivalent from Unconstrained Melody if you want generic type safety) to easily determine whether a particular value is a real value without worrying about the "fake" one too.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 4
    Interesting. Related: Why does FxCop complain about enumerations without a zero value (i.e. in enums that assign explicit values for each entry), suggesting a "None" entry with value 0? Doesn't it seem like adding an artificial "None" is a "fake" value like your answer states, therefore being an inferior solution? See: http://msdn.microsoft.com/en-us/library/ms182149(VS.80).aspx – Mark Carpenter Nov 25 '09 at 09:30
  • 6
    Perhaps the FxCop rule is older than nullable types? – Jon Skeet Nov 25 '09 at 09:32
  • 2
    Yeah, it's going back to my point about if you use a nullable then you get a sensible default, which is what that rule is trying to enforce. – Fiona - myaccessible.website Nov 25 '09 at 09:52
  • Good explanation, just checked out the code for the Unconstrained Melody project, very interesting stuff. I wonder what could with combining the DelegateConstraint concept with linq expressions... – LorenVS Nov 25 '09 at 10:18
  • 1
    Just had a discussion about this with my colleague, but if Jon Skeet says use nullable I guess my argument is invalid :) – Rytis I Jan 27 '16 at 08:15
  • @JonSkeet I think @MarkCarpenter misunderstood the FxCop rule. The [docs for CA1008](https://docs.microsoft.com/en-gb/visualstudio/code-quality/ca1008) only insist on a 'None' value for flag enums. For simple enums, it merely requires that a zero value is specified where that value is the most frequently used value. A nullable enum is valid where the variable is undefined (just like choosing between `int` and `int?`), but that is outside the scope of this rule which is only to protect against the enum being initialised to 0 without having a valid zero value (as enum is `Int32` by default). – Neo Nov 11 '19 at 13:36
  • 1
    @Neo: Right, that would make sense. – Jon Skeet Nov 11 '19 at 13:42
27

I agree with archimed7592 that there is a real difference between absent value and "Unknown" value.

Example:

"what is your blood type?"

  • Null = absent value --> question hasn't been answered --> ask the question

  • "Unknown" --> patient indicates he doesn't know --> order lab test for the blood type

8

You just have to decide whether you need a value to represent unknown values, or you do need a way to represent absence of any value.

In the case of a need to represent unknown values, an extra enum-member sounds good as a solution.

In case of a need to represent absence of any value, make it nullable.

Have in mind, that there is nothing wrong with having both "unknown" enum-member and the enum itself being nullable at the same time.

HTH.

HolisticElastic
  • 937
  • 8
  • 17
5

IT DEPENDS!

Bill Wagner has listed some good reasons to add an Undefined enum when it makes sense. I suggest that you find the full item, but here's a preview:

Item 8: Ensure That 0 Is a Valid State for Value Types

The default .NET system initialization sets all objects to all 0s. There is no way for you to prevent other programmers from creating an instance of a value type that is initialized to all 0s. Make that the default value for your type.

One special case is enums. Never create an enum that does not include 0 as a valid choice. All enums are derived from System.ValueType. The values for the enumeration start at 0, but you can modify that behavior...

Now, I have a situation where the users need to select some type from a ComboBox, or they can have no type selected. I am using an enum with a [Description("a description")] attribute as the object to be selected. If none/Unknown is a natural choice for an enum, then I would use that to represent that nothing is selected. Otherwise, I will use a Nullable<MyEnum>.

Community
  • 1
  • 1
Hamish Grubijan
  • 10,562
  • 23
  • 99
  • 147
2

If it's nullable, you'd get it as a default value, you'd get exceptions if you tried to use it when null (which is a good thing!)

Fiona - myaccessible.website
  • 14,481
  • 16
  • 82
  • 117
1

Everything changes if the enum is attributed with [Flags] Attribute.

    [Flags]
    enum FlagsEnum
    {
        None = 0,
        First = 1,
        Second = 2,
        Third = 4,
        FirstAndThird = 5
    }
LuckyLikey
  • 3,504
  • 1
  • 31
  • 54