5 things you should know about enums in C#
Last updated
Last updated
If you remember, enums can be int, but also short, uint and so on. How can you define which type to use?
It's simple, you can add it after the declaration of the enum:
and, if we look at the generated IL, we'll see the result:
The fact that you can define them as int and as uint is a hint (pun intended) that you can also use negative numbers as inner values:
If you set each element's value as a power of 2, as you did for Flags
you can write something like
Now imagine that you have to check many times if a beverage is a wine: you can repeat the check, or extract it to a separate method.
Or you can add a value to the enum:
This simplifies your code to
It's a small trick, but it can help you clean your code.
Now it's time to use enums for real-world scenarios: maybe a .NET Core 3 API?
I have created a simple API controller that returns a single movie:
What will this endpoint return? As you've already learned, internally an enum is nothing but a number, so the returned JSON will be this one:
Yes, I know, you were expecting the string value.
But you can have it by updating the Startup class:
or, if you want to set a serializer only to a specific enum, you can add an attribute to it:
Thanks to Insulind on Reddit I found out that actually the [Flags]
attribute's job is not to allow multiple values to be stored in a single field, but rather to have a better string representation.
If we remove the Flags attribute on the Beverage enum, we can assign multiple values as if it had the attribute enabled.
Everything works, even without the HasFlag
method. The difference comes if we get the string value of that variable: now it returns 9, because it's getting directly the numeric value.
If we put the Flags attribute, everything changes: the string value will be Water, RedWine, so the comma-separated list of their values.
This makes sense only if you use multiple values: as we've already seen, if you print a single value you'll get the string value of it.
If you remember when I talked about how to format an enum, you can use ToString("g")
and ToString("f")
to get the enum name. I specified that there is a small difference but I haven't explained what was it about.
If you set a combined enum value but you don't add the Flags attribute, you'll end up with different results:
On the contrary, if you add the Flags attribute, they all return Water, RedWine.
As always, there are some best practices you should follow. The following ones are about the usage of Enums with the Flags attribute.
Use only powers of two when defining flags, so that you won't overlap values when combining more enums; this will give you also the possibility to use bitwise operators, like OR, AND, and XOR.
You should add a None value, and set it to 0, to represent the lack of value. Of course, consider that HasFlag(EnumName.None)
will always return true.
In older versions of .NET, the HasFlag method was less efficient than a bitwise AND check. So, to check if a value contains Beverage.Water, you could do ((beverage & Beverage.Water) == Beverage.Water)
. With newer versions, this problem has been fixed.
As always, remember to validate input parameters, just like you should do for simple enums.
For more, you can refer to Microsoft documentation.
Here we've seen more things to know about enums. Probably you won't use all of these capabilities in real-world scenarios, but I think you should know that they exist.
To recap, we've seen that
You can change the underlying type to short, uint and similar;
You can also define negative values;
Inside the enum definition, you can create values that represent the union of other two (or more);
By default, .NET APIs return enum values as numbers; to fix it, you must add a configuration in your Startup class;
You can also omit the Flags attribute; the downside is that when you print the value of a variable that is the union of 2 enums, the returned string is the sum of the enums stored inside that variable, not the string representation.
Do you know something to add?
Happy coding!
https://www.code4it.dev/blog/5-more-things-about-enums-csharp