In this article, we will learn about how to write clean C# code. As we know that writing code is not much difficult, but writing clean and reusable code is not easy in work pressure time. but If you write better code your senior will impress more, which can help you in your career growth.
This will come from practice do more and more. so here we will cover the following things,
- Use a Good IDE
- Use Meaningful Names
- Use Case Notation
- Reuse Code
- Design Patterns
- Remove Unused Code
- Method Chaining
- Async/Await
- Ternary Operator
- Null Coalescing Operator
- Prefer String Interpolation
- Avoid Large Parameters in method
- Log Exception
Use a Good IDE
First of all before start to write the code choose best IDE for your code development. In case of C# code writing we have Visual Studio, Visual Studio Code it's free provided by Microsoft. As this IDE provided code fomatting and intellisens to correct our code.
Use Meaningful Names
You know if we work on bigger project then according to business need we required a lot of local variable and class proporty names. That at time we confuse to decide better name. but we should tale time and analyze the best name for any varible, class name or method name, parameter as well.
so it should be selft explanatory.
Here i am giving some example for this.
-
- int i1;
- string s1;
- date d1;
-
-
- int age;
- string name;
- date createdDate;
so that it will easy for other developer to understand the concept.
Use Case Notation
We should also follow that how Microsoft writing his code, so this is very easy to see just click on an inbuilt method to check for it's definiton, you will see a lot of method and proporty how microsoft define.
here is the example,
-
-
-
- public class RouteData {
-
-
-
- public RouteData();
-
-
-
-
-
-
-
-
- public RouteData(RouteData other);
-
-
-
-
-
-
-
-
- public RouteData(RouteValueDictionary values);
-
-
-
- public RouteValueDictionary DataTokens {
- get;
- }
-
-
-
-
- public IList < IRouter > Routers {
- get;
- }
-
-
-
- public RouteValueDictionary Values {
- get;
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public RouteDataSnapshot PushState(IRouter router, RouteValueDictionary values, RouteValueDictionary dataTokens);
-
-
-
- public readonly struct RouteDataSnapshot {
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public RouteDataSnapshot(RouteData routeData, RouteValueDictionary dataTokens, IList < IRouter > routers, RouteValueDictionary values);
-
-
-
- public void Restore();
- }
so I hope now we should clear to write the case.
In summany use can say that for camel case use the first letter of the first word of the variable will be in lower case, then after that use first letter of every other word that in upper case. This is for while naming your local variables and method arguments.
-
- int MyAGE
- string MYNaMe
-
-
- int employeeAge;
- string FirstName;
and for pascal case : the first letters of each words should be in Upper Case. We should use this kind of naming for Methods and Classes.
-
- addInteger(int a, int b);
- addEmployee(object emp);
-
-
- AddInteger(int a, int b);
- AddEmployee(EmployeeDto employee);
Reuse Code
As we know in coding a lot of code we can reuse if we thing before the implementation. so keep in mind whatever we are going to write the code we can resue in other places or not.
If we write the reusable code it will reduce a lot of line of code and makes it highly efficient. Other thing we should avoid to make a large class, always try to make it small size. As we know that Solid Principles, suggest you must segregate classes to small class so that we can use it as a single responsibilty function. So that it will helps us to acheive loosely coupled code.
Design Patterns
This pattern practice will come after experience and experience to write and think more code. Design patterns are basically patterns that can provide a resuable solution.
we have a lot of design pattern that need to learn.
Creational Design Pattern
- Factory Method
- Abstract Factory
- Builder
- Prototype
- Singleton
Structural Design Patterns
- Adapter
- Bridge
- Composite
- Decorator
- Façade
- Flyweight
- Proxy
Behavioral Design Patterns
- Chain of Responsibility
- Command
- Interpreter
- Iterator
- Mediator
- Memento
- Observer
- State
- Strategy
- Visitor
- Template Method
Note
This design pattern you can learn from any resources,Here I can suggest to go through with this;
Remove Unused Code
In general pracrice we are wrting code, then if we feel it is not in use then we are not removing the code and start wrting another code for the same. that is ok that you can take some refernce from your code. but I would suggest after finishing your logic and testing remove unused code, before checking, for reviewing with your senior.
Method Chaining
Method chaining is the concept that multiple method calling together.
This is one of the good example.
- services.AddHealthChecks().AddSqlServer(_configuration.GetConnectionString("DbConn"));
Here in this code we are calling three methods( AddHealthChecks, AddSqlServer, GetConnectionString) together.
The advantage of this, it will compile in a single line,
Let's take another example here:
- public string ReplaceStrings()
- {
- string name = "Hamid Ali";
- return name.Replace("H", "A").Replace("A", "B").Replace(" ", "_");
- }
I hope now it will be clear!!!
Async/Await
In latest version of C# Microsoft provided Asynchronous programming, this is a very good concept that we should go with this approach!
Asynchronous Programming helps us to improve the overall efficiency of application when dealing with large computation functions that can take some time to finish computing.
Because of such function executions, may take more time to complete application so it seem to be frozen to the end-user. This unnecessary time taken at UI side in bad for user experience. In this cases, we should use async methods to free the main thread.
Read async programming from here,
Avoid ‘throw ex;’ In The Catch Block
As we know for catching exception stack trace is important part. so if we use throw ex, we could loose to store stack trace. So better to use throw only in catch block
-
- try {
-
- } catch (Exception ex) {
- throw ex;
- }
-
- try {
-
- } catch (Exception ex) {
- throw;
- }
Ternary Operator
Ternary Operator is the concept that we can apply using ? and : symbol for checking conditio, as we can say that the alternative of if else condition. The other benifit is that it reduce the line of code.
Look this example,
-
- public string Validate(int age) {
- if (age == 10) {
- return "Age is 10";
- } else {
- return "Age is not 10";
- }
- }
-
- public string Validate(int age) {
- return age == 10 ? "Age is 10" : "Age is not 10";
- }
see this Ternary Operator reduces line of code and look much cleaner.
Null Coalescing Operator
For checking Null of any entity Microsoft provided ?? operator it is known as Null Coalescing. using this operator we can identify whether this given entity is null or not.
Example
- public Employee Validate(Employee employee) {
- if (employee != null) {
- return employee;
- } else {
- return new Employee() {
- Name = "Smith"
- };
- }
- }
Here in this example I took a class enployee and checking if employee is not or not.
Same thing we can do using Null Coalescing Operator as below it reduces line of code and look much cleaner.:
- public Employee Validate(Employee employee)
- {
- return employee ?? new Employee() { Name = "John" };
- }
String Interpolation
For adding any number of string in general we are using + operator, but in C# 6, the String Interpolation feature was introduced.
Using + operator,
- public string Employee Validate(Employee employee)
- {
- return "Employee Name is " + employee.Name + ". Age is " + employee.Age;
- }
so we should take this advantage
usong $ sysmbol
- public string Employee Validate(Employee employee)
- {
- return $"Employee Name is {employee.Name}. Age is {employee.Age}";
- }
for small kind of method we should use that Expression Bodied Methods
- public string Message() => "Hello World!";
Avoid Large Parameters in method
some times we required to pass a lot of parameter, in this case we should avoid to pass large parameter. Insted of this we can create an object and pass in method parameter.
Here in thid example we can see that,
-
- public Employee Validate(int id, string name, string company, string city, int age, DateTime dateOfBirth) {
- return new Employee() {
- Age = age,
- Name = name,
- Company = company,
-
- };
- }
-
- public Employee Validate(Employee employee) {
- return employee;
- }
Log Exception
This is a good approach to add try catch block and log the error.
-
- public void Validate(Employee employee) {
- try {
- TODO();
- } catch {}
- }
-
- public void Validate(Employee employee) {
- try {
- TODO();
- } catch (Exception ex) {
- LogException(ex);
- }
- }
Summary
Congratulations on following the steps and reaching out here. I hope you liked this tutorial and please share it with others.
Do you have any suggestions or additions? Please mention below in comment section. Thanks for taking your valuable time to read the full article.