Should an Enum start with a 0 or a 1?
Imagine I have defined the following Enum:
public enum Status : byte
{
Inactive = 1,
Active = 2,
}
What's the best practice to use enum? Should it start with 1
l开发者_C百科ike the above example or start with 0
(without the explicit values) like this:
public enum Status : byte
{
Inactive,
Active
}
Framework Design Guidelines:
✔️ DO provide a value of zero on simple enums.
Consider calling the value something like "None." If such a value is not appropriate for this particular enum, the most common default value for the enum should be assigned the underlying value of zero.
Framework Design Guidelines / Designing Flag Enums:
❌ AVOID using flag enum values of zero unless the value represents "all flags are cleared" and is named appropriately, as prescribed by the next guideline.
✔️ DO name the zero value of flag enums None. For a flag enum, the value must always mean "all flags are cleared."
Well, I guess I stand in disagreement with most answers that say not to explicitly number them. I always explicitly number them, but that is because in most cases I end up persisting them in a data stream where they are stored as an integer value. If you don't explicitly add the values and then add a new value you can break the serialization and then not be able to accurately load old persisted objects. If you are going to do any type of persistent store of these values then I would highly recommend explicitly setting the values.
An Enum is a value type and its default value (for example for an Enum field in a class) will be 0 if not initialized explicitly.
Therefore you generally want to have 0 as an defined constant (e.g. Unknown).
In your example, if you want Inactive
to be the default, then it should have the value zero. Otherwise you might want to consider adding a constant Unknown
.
Some people have recommended that you don't explicitly specify values for your constants. Probably good advice in most cases, but there are some cases when you will want to do so:
Flags enums
Enums whose values are used in interop with external systems (e.g. COM).
Unless you have a specific reason to change it, leave enums with their default values, which begin at zero.
public enum Status : byte
{
Inactive,
Active
}
I would say, it depends on how you use them. For flagging enum it is a good practice to have 0 for None
value, like that:
[Flags]
enum MyEnum
{
None = 0,
Option1 = 1,
Option2 = 2,
Option3 = 4,
All = Option1 | Option2 | Option3,
}
When your enum is likely to be mapped to a database lookup table, I'd start it with 1. It should not matter much for professionally written code, but this improves readability.
In other cases I'd leave it as it is, giving no care whether they start with 0 or 1.
Unless you have a good reason to use the raw values, you should only ever be using implicit values and referencing them with Status.Active
and Status.Inactive
.
The catch is that you might want to store data in a flat file or DB, or use a flat file or DB that someone else created. If you're making it yourself, make it so the numbering fits what the Enum is used for.
If the data is not yours, of course you're going to want to use whatever the original dev had used as a numbering scheme.
If you're planning on using the Enum as a set of flags, there is a simple convention that's worth following:
enum Example
{
None = 0, // 0
Alpha = 1 << 0, // 1
Beta = 1 << 1, // 2
Gamma = 1 << 2, // 4
Delta = 1 << 3, // 8
Epsilon = 1 << 4, // 16
All = ~0, // -1
AlphaBeta = Alpha | Beta, // 3
}
Values should be powers of two and can be expressed using bit-shift operations. None
, obviously should be 0
, but All
is less obviously -1
. ~0
is the binary negation of 0
and results in a number that has every bit set to 1
, which represents a value of -1
. For compound flags (often used for convenience) other values may be merged using the bitwise or operator |
.
If not specified numbering starts at 0.
It is important to be explicit since enums are often serialized and stored as an int, not a string.
For any enum stored in the database, we always explicitly number the options to prevent shifting and reassignment during maintenance.
According to Microsoft, the recommended convention is use the first zero option to represent an uninitialized or the most common default value.
Below is a shortcut to start numbering at 1 instead of 0.
public enum Status : byte
{
Inactive = 1,
Active
}
If you wish to set flag values in order to use bit operators on enum values, don't start numbering at the zero value.
I would start a boolean type enum with a 0.
Unless "Inative" means something other than "Inactive" :)
This retains the standard for those.
I'd say best practice is to not number them and let it be implicit - which would start from 0. Since its implicit its the language preference which is always good to follow :)
Don't assign any numbers. Just use it like it supposed to be used.
If you start at 1, then you can easily get a count of your things.
{
BOX_THING1 = 1,
BOX_THING2 = 2,
BOX_NUM_THING = BOX_THING2
};
If you start at 0, then use the first one as a value for uninitialized things.
{
BOX_NO_THING = 0,
BOX_THING1 = 1,
BOX_THING2 = 2,
BOX_NUM_THING = BOX_THING2
};
First of all, unless you're specifying specific values for a reason (the numeric value has meaning somewhere else, i.e. The Database or external service) then don't specify numeric values at all and let them be explicit.
Second of all, you should always have a zero value item (in non-flags enums). That element will be used as the default value.
Don't start them at 0 unless there's a reason to, such as using them as indices to an array or list, or if there's some other practical reason (like using them in bitwise operations).
Your enum
should start exactly where it needs to. It needn't be sequential, either. The values, if they are explicitly set, need to reflect some semantic meaning or practical consideration. For example, an enum
of "bottles on the wall" should be numbered from 1 to 99, while an enum
for powers of 4 should probably start at 4 and continue with 16, 64, 256, etc.
Furthermore, adding a zero-valued element to the enum
should only be done if it represents a valid state. Sometimes "none," "unknown," "missing," etc. are valid values, but many times they are not.
if the enum starts with zero then no need to assign integer values.It starts with 0 & increment by 1. Inactive = 0, Active = 1.
public enum Status : byte{
Inactive,
Active
}
If you want to assign specific value for 1st one, you need to assign the value for it.Here, Inactive = 1, Active = 0.
public enum Status : byte{
Inactive =1,
Active =0
}
Prefer setting the first Enum member's value to 1
if the Enum does not have a concept of default value for the following reasons.
Intuition
C# sets the Enum to 0
by default. So, unless that first Enum member is really a default value, it's intuitive to not have it mapped to 0
.
Allows Enforcing of Required Enums for Web API
Consider the following Minimal Web API:
using Microsoft.AspNetCore.Mvc;
using MiniValidation; // See https://github.com/dotnet/aspnetcore/issues/39063
using System.ComponentModel.DataAnnotations;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
// Returns true if validation is successful, false otherwise
app.MapGet("/", ([FromBody] MyClass myClass) => MiniValidator.TryValidate(myClass, out _));
app.Run();
class MyClass
{
[EnumDataType(typeof(MyEnum))] // Validates `MyEnum` is a valid enum value
public MyEnum MyEnum { get; set; }
}
enum MyEnum { One, Two }
Suppose that it's mandatory for the client to supply a value for MyEnum
; sending an empty JSON string {}
results in the endpoint returning false
.
However, the above implementation returns true
; Model Validation passes because C# defaults MyEnum
to 0
, which is mapped to MyEnum.One
.
By modifying the Enum to enum MyEnum { One = 1, Two }
, the endpoint returns false
; Model Validation fails because none of the Enum's members are mapped to 0
.
Caveat
Enum's guidelines documentation state
DO provide a value of zero on simple enums.
But it doesn't seem that violating this guideline leads to negative consequences.
I like to start my enums at 0, since that's the default, but I also like to include a Unknown value, with a value of -1. This then becomes the default and can help with debugging sometimes.
精彩评论