Regions feature in C# is frowned upon by many. There are good reasons for that. In this post, I’d like to discuss why exactly you should avoid using them.
C# regions on the class level
Regions are one of the strongest smells in the C# language in a sense that it’s hard to come up with a justification for their usage. If you see one in code, it’s almost always a sign of a bad design decision.
Let’s take a couple of examples. Here’s one of the most common use cases I see in which regions are involved:
It might seem compelling at first, especially if you are used to this style of programming. There are several problems here, however.
This style is often aimed to hide the fact that a class is too large and thus violates the Single Responsibility Principle. The problem here is that the use of regions doesn’t solve the underlying problem but rather amplifies it even more making it’s harder for programmers to see the issue. If there’s a problem with code, don’t hide it. State it. Make it explicit by removing the regions and try to solve it after that. The solution is often as simple as splitting the class into several ones.
One might argue that large classes are not the only use case for regions and that they can be applied to relatively small classes as well. Indeed, I saw code bases where regions were part of the code style and were used almost everywhere. It wasn’t unusual to expand a couple of folds and see that there’s effectively nothing inside:
So, would small classes be a good use case for them? No. While there are admittedly merits in such approach, one of them being a standardized code style, its drawbacks are much more substantial:
- Regions hide the perspective. It’s hard to see what’s going on in the file you just opened. It requires you to take an additional action (unfold a region) which essentially results in poor user experience for developers.
- Regions encourage programmers to group methods by their visibility and/or implementation details, not functionality. Of course, regions don’t entail such behavior per se but I see it a lot because, well, such segregation is easier to perform and standardize. It’s a good idea to group the class methods by their purpose even if it means you need to combine a property and a backing field or a public and a private method together. Such practice leads to better cohesion.
- If not used for hiding large code chunks, regions don’t provide additional value and thus should be removed due to the Yagni principle. If a class is small enough, why even bother trying to hide different pieces of it?
C# regions on the method level
Although regions inside a method are less common, they sometimes take place as well. Let’s look at this example:
The problems with this method are essentially the same. In addition to sweeping the problem under the carpet, regions act as comments here. As any comments used inside a method, they signalize an issue with the code readability. Instead of hiding parts of the method under regions, it’s better to refactor it and extract the “Create an object”, “Perform an action” and “Save the object” portions into separate functions.
The “Parameter validation” part is a bit trickier. Large validation sections is a strong sign of primitive obsession. To solve this problem, create separate classes for notions in your domain model instead of using primitive types to represent those notions.
Any good use cases for C# regions?
Despite all said above, I personally think there are a couple of good use cases for regions in C#.
The first one is legacy code bases. It’s not always possible to break large classes into smaller ones when you work on a legacy project. At the same time, you may need to extend it in some way: fix bugs, add new functionality, etc. In this case, it would be probably a good idea to mark the “dark area” with several regions to help yourself orientate in it.
Another use case is some hack which you deliberately inject in your code. An example here would be email templates. If there are only a few of them and they don’t change often, it might be easier to just include the templates into C# code instead of using separate HTML files. If this is the case, you may employ regions to isolate the template text from the code.
It’s important to note that these use cases should be viewed as exceptional or, even better, temporary. They shouldn’t occur too often.
The biggest problem with C# regions is that they hide problems with code. If you see a region in your code, try to remove it and fix the underlying issue.