You're Using Enums in C# Wrong - So Do This!
November 8, 2023
• 1,464 views
In this video series, we've been looking at enums in CSharp. We've started with the basics and after going through some examples... It's time for the hard truth. You're using Enum wrong. But don't worry - We'll go through what the hidden costs are so you can avoid any issues.
Have you subscribed to my weekly newsletter yet? A 5-minute read every weekend, right to your inbox, so you can start your weekend learning off strong:
https://subscribe.devleader.ca
Check out more Dev Leader content (inc...
View Transcript
it turns out you're probably using enums wrong and I mean I can't possibly know this for sure but statistically from what I've seen in code bases I don't think people are using enums properly in this video we're going to walk through some code where I show you some different usages of enums and why I think that we're not set up for Success when you use enums in this particular way if you're still new to using enums or you're not really familiar with them you can go ahead and watch this video here and that's going to walk you through this video series to bring you to this point where we talk about enom us M before I jump over to visual studio just a quick reminder to subscribe to my free Weekly Newsletter I try to include an exclusive article and early access to a video
that will be coming out on my YouTube channel the next week there's also some coding tips and coding exercises as well as a recap on the different content that I've shareed from the week There's no catch no strings attached and it's totally free so I'll include the link in the comments below and you can check that out I'll keep the rambling short let's get over to visual studio and talk about why I think people are using enums the wrong way all right on my screen I have a product enum that I've defined and we can see that we have some things like courses in here some subscriptions and some eBooks and this is a pretty common pattern that I see when people are declaring enums and the thing that I want to call out here is that this is a set of values that is
not necessarily fixed and what do I mean by that well perhaps if I were to only ever offer three courses three subscriptions and three ebooks this would be considered a fixed set of values but the reality is if I were creating courses and subscriptions and ebooks it would be in my best interest to continue offering more and that's going to mean that this enum is growing and changing over time and for example adding a new course is simply adding a new entry to this enum but what happens if I want to turn off a course what if I never want to sell it again and I want to make sure that it doesn't exist to my code the implications of having enums that have sets of values that can change are are very significant and while this is a really common practice that I see
people using enums for I think that the correct way or the safest way to use an enum is to use it on sets of data that are not ever changing and sometimes that feels a little bit constrained because not ever changing like how do we possibly know if it's never going to change well consider things that either do never change or should be changing extremely infrequently an example of things that never change are the days of the week the days of the week are a great example for an enum because you can declare it once and it should never have to change the same thing with months of the year that's something that is fixed it's finite and it's never going to change you may also have situations where you have something like a state machine in your code and if there's a finite set
of States you might be in a great position to use something like an enum to represent those different states however even something like a state machine that may grow over time and change over time even if it's unlikely that might mean that we have some of these costs of an enum changing which we'll walk through in just a moment so before we look at some more code for how we consume the enum I just wanted to pause for a moment to say that this is my interpretation of best practices for using enums I don't mean to tell you this like you can't ever use an enum in the way that I was just illustrating with the different products and subscriptions and things like that you can do it but I think there's going to be ca in there and you may want to avoid doing
something like this because I think that the overhead and the repercussions of doing that are a little bit hidden up front and they're costly down the road so it's not that you can't it's just that I think that there are better ways to do it when you have an enum that is a fixed set of values you're not going to run into these same challenges you can rest assured that when you're consuming that enum you have code that you can write that's operating on a fixed number of different states for that enum that means that your air handle can be greatly reduced and you don't have to worry about edge cases that might exist or might not exist in the future so let's go see what I mean by that so if we want to go see how we can consume this product enum I
just wanted to walk through some example code that's a little bit contrived but it shows you some different patterns for how things get consumed one really common primitive case that most people notice and try to move away from is a big chain if else statement so for example here I'm doing a product check if the product is Dev leader subscription one go do some stuff otherwise if it's course one go do some other stuff and we could go continue this pattern doing some handling in here and then having some else condition for some exceptional case or maybe we want to log something or do some other Behavior but the point is that we have this big IFL statement that's built up if we're dealing with an enum that has a fixed number of values for its entire lifetime of your application so again something like
days of the week months of the year something fixed that means that if we go write this if statement and it's a little bit ugly at least the different conditions that we have to check for are a finite number of states if you have something that could possibly be growing or changing in any way that's going to mean that this code eventually has to be updated to handle it otherwise if it's not you may run into situations where you're hitting this exceptional case more often than you should or it's going to mean that if you remove something from the enum perhaps you have to come over to this code and go delete an else condition and while that might not seem so bad in this example the reality is that when we have enum usage in a code base it's very common that we'll have
sets of if else statements like this scattered around different spots and each spot that we go have some type of if else statement like this it's going to mean that when we update that enum we have to go update all of those spots as well it becomes something something that seems simple on the surface and seems perhaps readable and understandable in this context but there's a maintenance burden associated with that every time you want to go touch that enum so the next thing that people might say is well let's go improve this because in if L statement is pretty nasty we can go use something like a switch statement instead and you can so I've demonstrated that here where you can go add new cases or remove them you have a default to go handle the exceptional case or however you want to handle something
that's not in this enum set the problem is still the same thing if you're ever changing the different values that are inside of this product enum you do have to go touch all of the places consuming it so that will mean just like the if statements that if you have something not handled by a case because you've gone ahead and added a new product you might be hitting this block of code more frequently and the inverse if you go remove something it's going to mean that anytime you have a switch statement anywhere in your code that's working on the product enum type you may have to go remove a case that was accounted for in the first place so the switch statement might look a little bit cleaner might make some people more happy to work with it's still the same type of problem and
then people might say okay well if statements and switch statements those really suck for this kind of thing but we can go make a mapping of all of the different enum types that we have and how to handle that so I'll demonstrate that as as well and we have it here and I've kind of indicated that something like this declaration probably belongs at a class level or something not directly in a method that would be executed every time but how does this end up working well if we have a lookup where we can go check for the product type and we can go ask to try to get the value out of it and then execute the Handler here and if it's not there we have this lse condition that's just like the other scenarios what does this look like if the product is changing
well if we go add a new product we still have to go add a new entry into this mapping so if we don't go do that especially because this could and probably will exist in multiple spots in the code base we're going to be hitting this exceptional case more often and again if we remove a product it's the same thing where we have to go update this mapping so you can keep thinking up different variations of how you can go handle this whether it's if statements switch statements maps and different lookups whatever it happens to be the point is that it's not actually going to matter yes doing that kind of stuff can help improve the readability of your code but I think that the reality is that if you're dealing with a fixed enum that kind of stuff is going to be helpful but
when it's not a fixed enom and it can change over time the real problem is how many spots in your code you're doing that so you can totally refute everything I'm saying if you're suggesting that you only have one spot in your code that has an enum like that and you want to work with it and that way you're moving from a switch statement to a look up if that's in a dictionary sure like that's going to help improve the readability in my opinion at least and it will not have the same problems that I just explained because you'll only have to update it in one spot that's great so I'm not trying to say conclusively as a rule you can never do this in fact I'm saying it's the opposite you could go ahead and do this and I've worked in very successful produ
code bases that had stuff like this scattered everywhere multiple different enums like this in many different spots I'm sharing this with you from my own personal and professional experience over a decade of working in C of people using enums in different ways what I found is that when you're using enums that are a fixed number of different states that you can exist in refactoring things from changes doesn't have to happen because you're not changing the number of enum States that can exist when you have enums that can change in the number of different values inside of it and you have more than one spot in the code base that needs to account for that you're increasing the amount of Maintenance and work that you have to do every time you touch it if it is something that's going to change but it's extremely rare that
maintenance overhead is greatly reduced so that's a really good position to be in I've seen this when people are creating State machines where at some point in time there's a finite set of States and the state machine works really well and they're using enums for those States so there may be a handful of different spots that check those enum values it all works it's great and then maybe a year down the line someone goes you know what we have to revamp this state machine to account for something else we'll extend it they go update that enum so there's one new state and at that point in time they're paying that maintenance cost for having a few things scattered around checking the enum so does that mean that they made the the wrong decision well no not necessarily it's a low maintenance cost when it's changing
either never or infrequently but for something like a product that I just demonstrated in these earlier examples if you have a set of products that you're extending or changing or altering in whatever way it's going to mean that that enum is probably changing semi-regularly and the maintenance overhead like I said is going to be pretty dramatic depending on how many spots you have it so t Dr if you can please try to keep your enims to a finite set of things otherwise an enum might not be the right thing for you again this is my opinion from my professional experience and I think that it's important to take different perspectives into play so if you want to see me explain more about that concept of interpreting different perspectives watch this video next
Frequently Asked Questions
What are enums in C# and how should they be used?
Enums in C# are a way to define a set of named constants. In my opinion, they should be used for fixed sets of values that don't change over time, like days of the week or months of the year. Using enums for values that can change frequently, like products or subscriptions, can lead to maintenance challenges.
What are the potential issues with using enums for changing values?
When you use enums for values that can change, you may face significant maintenance overhead. Every time you add or remove a value from the enum, you have to update all the places in your code that reference that enum. This can lead to increased chances of errors and a lot of extra work down the line.
Can I still use enums for values that might change occasionally?
Yes, you can use enums for values that might change, but I recommend doing so with caution. If you have a finite set of states, like in a state machine, it can work well. Just be aware that if those values change frequently, it will increase your maintenance burden.
These FAQs were generated by AI from the video transcript.