makerofthings7
makerofthings7

Reputation: 61463

How does this work, where an Enum is set a value twice within the same declaration?

This enum is within some C# source code and has its value reset many times. How does it work, and why would someone do that?

internal enum RequestType : ushort
{
    #region Asynchronous messages
    Shutdown = 0,
    BulkMessage,
    #endregion

    #region Synchronous message without response
    P2PBarrier = 0,
    Heartbeat,
    ReportProxy,
    LoadStorage,
    SaveStorage,
    ResetStorage,
    #endregion

  // This series repeats 
}

Upvotes: 1

Views: 176

Answers (1)

Robby Cornelissen
Robby Cornelissen

Reputation: 97140

As per the C# language specification (14.3 Enum members), there is nothing that keeps you from using duplicate enum values:

Multiple enum members may share the same associated value. The example

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

shows an enum in which two enum members—Blue and Max—have the same associated value.

As to how values are associated with enum constants when they're not explicitly defined, the spec (1.10 Enums) has the following to say (emphasis mine):

When an enum member declaration does not explicitly specify a value, the member is given the value zero (if it is the first member in the enum type) or the value of the textually preceding enum member plus one.

So the enum in your question is equivalent to:

internal enum RequestType : ushort
{
    #region Asynchronous messages
    Shutdown = 0,
    BulkMessage = 1,
    #endregion

    #region Synchronous message without response
    P2PBarrier = 0,
    Heartbeat = 1,
    ReportProxy = 2,
    LoadStorage = 3,
    SaveStorage = 4,
    ResetStorage = 5,
    #endregion
}

As to why someone would use this approach, the only reason I can imagine (besides saving a couple of bytes) is that the same enum can be used in different contexts in an idiomatic way. For the given example, the author doesn't need to pollute the namespace with separate SyncRequestType and AsyncRequestType enums, but is still able to make idiomatic use of the constants in both contexts.

I will withhold my value judgement, but the obvious downside of this approach is that you lose compile-time checking and nothing prevents you from using constants that don't have any meaning in a given context (e.g. applied to your example, using a synchronous message type in an asynchronous context).

Upvotes: 4

Related Questions