31 Best Clean Code C# Tips of 2023


Hey, let me know if this is you:

You are a developer, but instead of DEVELOPING new code, you spend most of your time fixing code that is already in use? Produced by developers who are not in your company anymore.

Look, code is a living thing.

Even if you are working on an entirely new code at the moment, it will evolve. And the better you write it, the more likely it will be useful for you and someone else.

But when you’re writing code that isn’t very readable, you can be sure that no one else won’t like to work with it.

Or even worse, they might break it when they try to change it. Ooops.

Clean code is C# code that is easy to read and understand, both for the original author and any future developers who may need to work on the codebase. It is a code that follows best coding practices and is organized in a logical way.

You know that poorly written code can be a nightmare to maintain and update.

However, if you follow some simple best practices, you can keep your code clean and organized, making it easier to work with and less prone to errors.

If you want to become a better developer, you should read this article. It has 31 of the best tips for writing clean code in C#, compiled from experts in the software development field.

What is clean code in C#?

Writing good code is a skill that you can learn, and it’s a skill that every programmer should possess.

However, it’s not an easy skill to master. It’s not something that most programmers take the time to learn. Most developers are just happy to copy and paste the solution from the Stack Overflow, make tiny changes until it works, then move on to the next task.

But if you want to become a better developer, you need to take the time to learn how to write clean code.

Clean code is a term used in software development to describe code that is easy to read, understand, and maintain. When you write clean code, other developers can easily understand it and change it.

You will easily recognize bad code, though. Bad code is code that has not been built with care. It is often rushed and put together in a way that doesn’t make sense. But this can make the life of the programmer that has to maintain it more difficult. Poorly written code can be challenging to read and understand, leading to mistakes and frustration. On the other hand, clean code is also easier to debug and fix when there are problems.

If you are looking for some great advice on how to write clean code in C#, you are at the right place. This article has 31 of the best clean code concepts for writing clean code in C#.

#1 Follow the Boy Scout Rule

Always leave the code better than you found it.

Robert C. Martin

The desire for having a better code needs to come from inside you. You need to realize that the code you make will someone else have to maintain in the future. That someone else could be you. Or it could be any other developer. The better the code, the easier the future job will be.

The Boy Scout Rule is a coding principle that says that when you’re working on code, you should leave it in a better state than when you started working on it. This means taking the time to clean up any messes, testing your code, and making sure everything works as it should. It can be hard to resist the temptation just to hack together a quick solution, but taking the time to do things the right way will pay off in the long run.

Not only will your code be easier to read and maintain, but you’ll also avoid the headaches that come with debugging broken code.

Despite its simplicity, this coding standard is tough to follow. It requires a lot of work and discipline.

However, if you do follow the rule, you will notice the difference in the long term. You might get praises for your work from fellow developers. Heck, they may even stand up and applaud you.

#2 Use the best available IDE

An Integrated Development Environment (IDE) is a software application that provides comprehensive features to software developers for software development. IDEs usually consist of a source code editor, build automation tools, and a debugger.

Choosing the best IDE can be a challenge. That is, unless you are a C# developer. Then it’s easy. Just use Visual Studio 2022. Its Community version is free, and it includes plenty of features to help you code efficiently.

If you are looking for a more advanced IDE, a paid version of Visual Studio includes lots of great features for advanced developers. Another great alternative is JetBrains’ Rider.

#3 Use a version control system

If you’re writing a piece of software, you should use a version control system.

Version control systems are important when working on code because they allow you to track the changes made to your code and merge changes from other developers. They help you maintain a code history and make it easier to track down and fix bugs.

You can also quickly revert to an earlier version if you make a mistake.

Even if you are working alone, use the version control system. Rather than manually backing up your code to another folder every time you make a change, the version control system does this for you automatically.

The best-known version control systems are Git, Mercurial, and SubVersion (SVN).

#4 Don’t use a lot of comments

Don’t comment your code. Rewrite it!

Brian W. Kernighan and P. J. Plaugher

Programming is all about solving problems, and the best way to do that is by writing clear, concise code. Adding comments to your code can make it more readable. However, using too many of them can make your code harder to follow. So try to avoid using comments whenever possible – your code should be self-explanatory. If you do need to add comments, use them sparingly and only when they’re really necessary.

In the past, people would add many comments to their code because they thought it was suitable for the project. And they saw everyone else was adding comments everywhere. But, in reality, it wasn’t. It was just there for the sake of having more comments. It didn’t add any value to the code.

#5 Use the proper naming convention

It’s important to name your variables, classes, and methods appropriately. That way, you can quickly identify them.

The following table shows the naming convention you should use while writing C# code. It’s pretty much a standardized way of writing code.

TypeNaming convention
Method parametercamelCase
VariablecamelCase
NamespacePascalCase
ClassPascalCase
Method namePascalCase
PropertyPascalCase
Field_camelCase

Variable and method names should be as descriptive as possible. They should help you understand what they are used for. For example, if you’re working on a project that has a class named Order, you might use a variable name like existingOrder. Based on the variable’s name, you can probably figure out that it contains an existing order. And it probably belongs to the code that updates the orders in the system.

Avoid having shorOften in the code, you see names that are, for lack of a better term, weird. For example, you might find a variable named “x”.

int x = 0;

Or a method named “ThisMethodDoesSomething”. What does “x” mean? What does the method “ThisMethodDoesSomething” actually do? The only way to answer those questions is to debug through the code until you are familiar with it. And that takes precious time away from you.

#6 Your code should be correctly formatted

Most developers know that a clean and well-organized code is the key to a good project.

However, there are many reasons why you should care about code formatting. For example, it’s one of the first things a reviewer will look at when reviewing your code. It also helps with refactoring and maintenance since it makes the code easier to understand and makes it easier to spot potential bugs.

Also, there is a nice little trick you can use to indent your code automatically. Delete the last closing squiggly bracket and add it again. That will immediately format your code.

The alternative is to use Ctrl + K, Ctrl + D keys combination to fix the formatting within the file.

The third way to run Code Cleanup inside Visual Studio is to click on the broom icon.

Code cleanup action
Code Cleanup

That will run the following actions:

  • Format document
  • Remove unnecessary usings
  • Sort usings
  • Apply file header preferences
Code Cleanup options

You can also modify the cleanup profile to add even more automatic fixers. Pretty sweet, huh?

#7 Keep your code organized within folders inside the solution

When working on a project, it is crucial to keep your code organized. You can do this by creating folders inside of the solution. The folders will make finding the code you are looking for easier. You can also create sub-folders to organize your code further. They will make it easier to find and edit specific code.

In Visual Studio, you can also include Track Active Item in Solution Explorer. That will automatically select the opened file inside the solution explorer. So you don’t have to search for it if the solution is big.

To enable this option, go to Tools -> Options -> Project and Solutions -> General and enable the “Track Active Item in Solution Explorer” option.

Track Active Item in Solution Explorer

#8 Write short methods when developing code

When writing code, use short methods. Short methods keep your code more organized and readable. Short methods are also easier to debug. If there is a problem with a method, you can quickly isolate it and fix it. That is much harder to do if the method is long and complex.

Additionally, if you need to change to a lengthy method, you may have to scroll through a lot of code to find the right place.

How to reduce long methods? Use Extract Method refactoring.

It is an easy way to bring any method under control quickly.

The Visual Studio can do this automatically for you:

Easy, right?

For more information on how to perform this refactoring and why it’s one of the most critical refactorings, read this article.

You might ask one final question: Is there a magic number on how long the method should be? No. It should be long enough to do only one thing. But it should not have more than, let’s say, 20-30 lines. Of course, your method could be longer and be perfect, but try to keep them as short as possible.

#9 Methods shouldn’t have too many parameters

Methods in your code shouldn’t have too many parameters. Having too many parameters for a method can make it difficult to understand and use.

In addition, it makes your method harder to reuse. Try to limit the number of parameters a method has to four or five.

I know, I know. In the Clean Code book, Robert C. Marting (aka Uncle Bob) suggests that you shouldn’t have more than three parameters. While it’s good advice, often it’s too restrictive. Based on my personal experience, I find 4-5 parameters an upper limit on method parameters.

What to do when your method has more than 4-5 parameters, and you need to add one more?

For example, take a look at this method:

public void SaveHomeAddress(string name, string homeAddress, string country, string email, string fileLocation)

The solution is to use the Parameter Object Refactoring to fix the problem of having an excessive amount of method parameters:

public void SaveHomeAddress(AddressDetails addressDetails)

In the above example, the AddressDetails method has all the properties that the SaveHomeAddress needs. If you want to learn how to safely apply this refactoring, then this article will show you how to do that.

#10 Avoid complicated conditional logic in your code

Complicated conditional logic is a code smell that can lead to errors. Someone modifying the code will inevitably break the logic, leading to difficult-to-find bugs. Use simple conditional logic whenever possible. If the code is more complicated than it needs to be, break it into smaller functions.

There might be cases in your code where you have nested conditional logic. You know, if inside if, inside if. I call that code Ifception.

The easiest way to refactor nested if statements is to use a guard clause. Visual Studio has the Invert if code fix for nested if statements.

invert if
Visual Studio Invert if option

#11 Eliminate dead code

Unused code is a massive problem in most software projects. When you start changing code, you sometimes have a lot of extra code that loses its usage. At first, it’s not a big deal. One small unused variable here, one extra unused method parameter there. But these things keep adding over time.

Any extra code makes software harder to change. It increases the time it takes to make a change, making it more likely that the change will break something else. When your software is hard to change, it is more likely that you will leave problems in the software or create new bugs.

One of the best ways to write clean code in C# is to eliminate unused code. Therefore, when you write code in C#, you want to make sure that you are not wasting any space and that every line of code is being used.

Again, Visual Studio can help you eliminate dead code.

Remove unused member

#12 Eliminate God classes

A God class is a class that tries to accomplish everything, usually by extending another class or classes. They have many methods and properties, and they typically have no clear responsibility. These classes are hard to understand, hard to maintain, and hard to test. They’re often the result of code duplication, and they’re a significant problem in software development.

You should try to break a God class into little pieces to make it testable.

#13 Don’t optimize prematurely

You might think that optimizing is smart. Wait until you are sure that you need to optimize. Optimizing prematurely is a common mistake many developers make. They want to optimize the code they write at the very beginning. However, it’s better first to write readable code and then optimize it later.

Worry about performance issues once you finish implementing and after testing the feature. Now, if you find that some areas are absolutely critical and your performance is suffering, then go ahead and optimize that code, but only after you’re sure that you need to do so.

In all other cases, your code doesn’t need optimization.

#14 Think about exception handling and edge cases

One of the most common mistakes I’ve seen from new developers is not having an exception handler for statements that can go wrong. For example, if you have a line of code that opens the file and reads it, it’s a great idea to add a try-catch block around that code. If the file does not exist, this can throw an error.

Another big part of coding is edge cases. What is an edge case? An edge case is a situation where more outcomes could happen, and you want to be prepared for all of them. One of the best ways to make sure all edge cases are bug-free is to write unit tests for all possible scenarios.

The problem, however, is most people just don’t think of all the edge cases, and it causes a lot of bugs.

#15 Don’t write “clever code”

I am very careful not to write clever code that is not easy to maintain. I will often rewrite code that I think is clever and make it more straightforward. I will try to name variables and methods in the code as self-explanatory as possible. I do that to explain what I am doing to someone who sits down and looks at the code after me. I don’t ever want to return to my code in 6 months and not understand it.

#16 Avoid returning null as method result

Returning null is a common programming practice used when a method cannot complete its action. However, this is a big risk. You need to remember to handle the null result that the method returns.

Returning null can lead to NullReferenceException, and you might think you can’t avoid this exception, but you can.

A great feature that came out with the release of C# 8 is the Nullable reference types. It is a great way to reduce the throwing of NullReferenceException.

C# nullable context

#17 Write private code

You should always use private fields and methods as much as possible in your classes. This way, other classes can access only the minimum set of public methods. As a result, you can change the code at any time without worrying about anyone else accessing it.

It’s a very common pattern to make fields and methods public, even if they’re only used internally inside the same project. Of course, this is not a bad practice per see. But you should have in mind that you expose fields and methods used internally and that nobody should know about.

#18 Use the YAGNI principle

The YAGNI principle is often overlooked in the development process. It stands for “You Aren’t Going to Need It” and reminds developers only to build what is necessary. This principle can keep projects on track by preventing unnecessary features from being added and bogging down the development process. Following the YAGNI code style can reduce costs by preventing features from being built that may not be needed at all.

When using the YAGNI principle, remember that it should not be used as an excuse to avoid planning or to skimp on quality. On the contrary, careful planning and design are still essential, and you should only add features if they are indispensable.

#19 Use the DRY principle

Don’t repeat yourself principle (DRY) is a software design principle aimed at reducing the repetition of duplicate code in the application.

Every piece of knowledge in the code should have a single and unambiguous representation within a system. DRY is a valuable principle in software development that keeps a system clean and understandable. Before you start writing software, you should consider your coding style and use the DRY principle as often as possible.

If you find that you are repeating the same code repeatedly, it is time to refactor. One of the most straightforward solutions is to find a common piece of code (or data structures) and move it into a separate method using the Extract Method refactoring (see, I told you this refactoring is the best).

#20 Use the KISS principle

You should keep your code as simple as possible. It’s easy to get carried away with complicated code, but the KISS principle suggests otherwise.

The KISS principle says that “Keep It Simple, Stupid.” Therefore, follow this rule to increase the code quality.

The design of each module should be simple, straightforward, and should accomplish its task using the least possible number of entities. The KISS principle is especially notable as a software engineering heuristic. It is also an example of a design principle, a set of guidelines for the process of designing or creating a new system or implementing a new feature.

#21 Use SOLID principles

(Well, at least some of them.)

SOLID is an acronym for five coding principles for writing better code. These principles help develop any kind of application but have been especially useful for object-oriented programming.

The principles are:

  • Single responsibility principle: A class or a method should have only one reason to change.
  • Open/closed principle: A class should be open for extension but closed for modification.
  • Liskov substitution principle: Base type should be substitutable for child types without breaking the functionality.
  • Interface segregation principle: No client should be forced to depend on properties and methods it does not need.
  • Dependency inversion: High-level modules should not depend on low-level modules. They should depend on abstractions. Abstractions should not depend on details. Details should depend on abstractions.

Out of these five, I find that in 2023, only the Single responsibility principle and dependency inversion (in form of dependency injection) have remained highly relevant.

#22 Minimize the use of global variables

Every C# software engineer knows that using global variables is not good practice. But we do it anyway because it’s so convenient.

The fact that global variables are accessible from anywhere comes with a downside. Any changes to a global variable also affect everything else in the application. It is easy to see how, in a large application, the effects of a change to a global variable can be widespread and can have unexpected consequences.

Global variables make code harder to unit test, reuse, and maintain in general.

#23 Use constants instead of magic numbers/magic strings

Magic numbers are a bad practice that you should avoid in your code. They don’t provide any context to the value they represent, and they are hard to maintain since the value itself is hard to find.

if (itemsInCart < 5)

Now, tell me: what does the 5 in the above example represent? Who knows, right? It could be anything.

Use constants instead of magic numbers and strings when you have a value that doesn’t change and needs to be used in more than one place. Constants save time and reduce errors. Instead of looking up the number or string in more than one place, you simply have to change it in one place.

If the above example had the constant named MAXIMUM_SIZE_FOR_DISCOUNT:

if (itemsInCart < MAXIMUM_SIZE_FOR_DISCOUNT)

then you could assume that you can only apply a discount if there are less than 5 items in the shopping cart.

#24 Perform code reviews

One of the most important things when working in teams is to constantly improve the code that you write. But how do you ensure that you are writing code that is easy to read and understand? Code reviews are a great way to do that. They allow you to see how other developers see your code.

Having someone else look at your code can find errors that you may have missed. They can also suggest improvements to your code.

A code review doesn’t have to be something formal. It can be as simple as asking a colleague to look at your code to see if they can spot any improvements you can make.

Inside GitHub, you can use the Pull Requests for code reviews.

In addition, your pull requests (PR) should be small. Small PRs lead to smaller changes. More minor changes lead to less confusion when someone else reviews your PR. And your work gets reviewed and merged faster.

Code reviews are a big topic in itself. I suggest further reading two excellent articles from Michael Lynch:

#25 Unit testing

Unit testing is a process in which you check that the smallest testable parts of an application, called units, work as expected. You can perform unit testing on individual methods, classes, or modules.

Unit tests are written by developers as a form of automated verification and are often created as they write the code. Unit tests verify the code’s compliance with the user’s requirements and detect errors immediately upon introducing new code.

Writing a unit test is often an integral part of the development process. One of the main reasons for writing unit tests is to force the developer to think about how the new code will be used.

#26 CI/CD

Continuous integration and continuous delivery (CI/CD) are software development processes in which teams produce software in short cycles, ensuring that the software can be reliably released at any time.

Continuous integration is a development practice where developers integrate their work frequently. Ideally, each developer integrates their code at least once a day. The build system verifies each integration with an automated build. In addition, the build includes automated tests to detect any integration errors. This approach leads to fewer merge conflicts and fewer integration issues. The final result is working software at the end of every day.

With continuous delivery, every code change is integrated into a master (or main) branch, and that branch is continuously delivered to a set of users. The goal is to find bugs as quickly as possible in the software before it is delivered in a production-ready state to users.

#27 Don’t reinvent the wheel

A lot of developers love writing code. We love to create new little libraries and frameworks. But, sometimes, we forget that there’s no need to reinvent the wheel.

When you’re writing code for a project, there are certain things that you can go ahead and do yourself.

There are also things that you should never do. For example, if you need ORM (Object-Relational Mapping), use Entity Framework Core or Dapper. Don’t write your own. ORM can be an excellent solution for some applications. They’re easy to use, save you time and provide you with a huge range of functionality. Entity Framework Core and Dapper are both open source and easy to use, so it’s probably a good idea to pick one of them up and get going.

#28 Use the using statement

The “using” statement is a handy tool when writing code in C#.

You can use it to easily avoid memory leaks, which are common if you don’t use them. A memory leak is where the .NET garbage collector doesn’t know that your object is no longer being used. So, when you try to run your program, the .NET garbage collector will not free up memory because it doesn’t know that those objects are no longer needed. The using statement will solve this problem.

The next code shows how to use the using statement.

using (MemoryStream ms = new MemoryStream())
{
    using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateDecryptor(), CryptoStreamMode.Write))
    {
        cs.Write(cipherBytes, 0, cipherBytes.Length);
        cs.Close();
    }
    cipherText = Encoding.Unicode.GetString(ms.ToArray());
}

The using statement is a language element used in C# programs to reduce the amount of code you write to work with disposable objects.

For example, if you have a class used for opening and closing a file, you can use the using statement with it. The using statement will dispose the object when the using block ends.

#29 Use design patterns

Design patterns are reusable code solutions to commonly occurring problems in software applications. They are not solutions to specific problems but rather templates to commonly occurring problems in various contexts. You can reuse them in many different situations. In short, they’re a collection of best practices.

Design patterns can help you write better, more readable code and avoid writing redundant and error-prone code.

They are well-known to many programmers and have been cataloged in many books and websites. They are concise, and industry-recognized coding standards. They are widely used in a variety of programming languages.

#30 Get used to refactoring

Refactoring.

It can be a bit of a scary word for some developers. It sounds like you’re changing code and can be dangerous, right? Wrong. Refactoring makes your code better and is essential for writing clean code.

When you have some experience developing C# code, you start to notice that you can do things in a better way. The problem is that it’s harder to change existing code than to write new code. Luckily, refactoring is a skill you can learn. Very quickly.

The great developers are constantly refactoring their code, cleaning it up, and making it better.

They do this because they’re always learning new ways to write better code. They do this because they don’t want to look back at their old code in a year and say, “Why did I write it like that?”

They do this because they know that for every line of code they write, the codebase gets a little bigger, a little more complicated, and a little harder to work with. They don’t do it because they’re “clever”. They do it because they care about their craft.

#31 Always have in mind that you are writing code for humans

Any fool can write code that a computer can understand. Good programmers write code that humans can understand.

Martin Fowler

All the previous tips come down to one final tip: write your code for humans. They will have to read and understand it.

When you’re writing code, you’ll want to make sure that it’s easy for other people to understand. You need to make sure that you write it in a clear way and that it’s easy to follow.

Conclusion

It’s easy to produce new code.

It’s fun to produce new code.

It’s even easier to write bad code.

Writing bad code is faster.

On the other hand, writing clean code is hard. Writing clean code is not fun. Writing clean code is not easy. The dirty secret about clean code is that it is more work. It’s more work upfront, and it’s more work on an ongoing basis. Clean code takes more time to write and more time to maintain.

But when you follow good programming practices, you increase your productivity, happiness, and application quality.

Recent Posts