Writing clean code is essential for maintainability, readability, and scalability.

Here are 12 simple tips to help you write cleaner code in .Net, each illustrated with bad and good code snippets.

1. Use Meaningful Names

Bad Code

C#
public class C
{
    public void M()
    {
        var a = 10;
        var b = 20;
        var c = a + b;
    }
}

Good Code

C#
public class Calculator
{
    public void AddNumbers()
    {
        var firstNumber = 10;
        var secondNumber = 20;
        var sum = firstNumber + secondNumber;
    }
}

Explanation: Use meaningful names that explain the purpose of the variable, class, or method.

2. Avoid Magic Numbers

Bad Code

C#
public double CalculateCircumference(double radius)
{
    return radius * 3.14 * 2;
}

Good Code

C#
public double CalculateCircumference(double radius)
{
    const double Pi = 3.14159;
    return radius * Pi * 2;
}

Explanation: Use constants for magic numbers to make the code more readable and maintainable.

3. Use String Interpolation

Bad Code

C#
string name = "John";
int age = 30;
string message = "Name: " + name + ", Age: " + age;

Good Code

C#
string name = "John";
int age = 30;
string message = $"Name: {name}, Age: {age}";

Explanation: String interpolation is more readable and easier to manage than concatenation.

4. Avoid Deep Nesting

Bad Code

C#
if (user != null)
{
    if (user.IsActive)
    {
        if (user.HasPermission)
        {
            // Do something
        }
    }
}

Good Code

C#
if (user == null || !user.IsActive || !user.HasPermission)
{
    return;
}

// Do something

Explanation: Flatten your code by handling exceptional cases first and returning early.

5. Use Guard Clauses

Bad Code

C#
public void ProcessOrder(Order order)
{
    if (order != null)
    {
        if (order.IsValid)
        {
            // Process order
        }
    }
}

Good Code

C#
public void ProcessOrder(Order order)
{
    if (order == null || !order.IsValid)
    {
        return;
    }
    // Process order
}

Explanation: Guard clauses help reduce nesting and make the code more readable.

6. Use Dependency Injection

Bad Code

C#
public class UserService
{
    private readonly UserRepository _userRepository = new UserRepository();

    public void CreateUser(User user)
    {
        _userRepository.Add(user);
    }
}

Good Code

C#
public class UserService
{
    private readonly IUserRepository _userRepository;

    public UserService(IUserRepository userRepository)
    {
        _userRepository = userRepository;
    }

    public void CreateUser(User user)
    {
        _userRepository.Add(user);
    }
}

Explanation: Dependency Injection improves testability and maintainability by decoupling dependencies.

7. Single Responsibility Principle

Bad Code

C#
public class User
{
    public void AddUserToDatabase(User user)
    {
        // Add user to database
    }

    public void SendWelcomeEmail(User user)
    {
        // Send email
    }
}

Good Code

C#
public class User
{
    public void AddToDatabase(UserRepository userRepository)
    {
        userRepository.Add(this);
    }
}

public class EmailService
{
    public void SendWelcomeEmail(User user)
    {
        // Send email
    }
}

Explanation: A class should have one reason to change. Separate concerns into different classes.

8. Use Async and Await for Asynchronous Code

Bad Code

C#
public Task<string> GetData()
{
    return Task.Run(() =>
    {
        // Simulate long-running task
        Thread.Sleep(2000);
        return "Data";
    });
}

Good Code

C#
public async Task<string> GetData()
{
    await Task.Delay(2000); // Simulate long-running task
    return "Data";
}

Explanation: Use async and await for better readability and performance of asynchronous code.

9. Use Ternary Operators for Simple Conditions

Bad Code

C#
string status;
if (isActive)
{
    status = "Active";
}
else
{
    status = "Inactive";
}

Good Code

C#
string status = isActive ? "Active" : "Inactive";

Explanation: Ternary operators can simplify simple conditional assignments.

10. Encapsulate Conditionals

Bad Code

C#
if (age > 18 && !isMember)
{
    // Do something
}

Good Code

C#
if (IsEligibleForOffer(age, isMember))
{
    // Do something
}
private bool IsEligibleForOffer(int age, bool isMember)
{
    return age > 18 && !isMember;
}

Explanation: Encapsulate complex conditionals into methods to improve readability.

11. Avoid Using Static Classes for Everything

Bad Code

C#
public static class Utility
{
    public static int Add(int a, int b)
    {
        return a + b;
    }
}

Good Code

C#
public class Calculator
{
    public int Add(int a, int b)
    {
        return a + b;
    }
}

Explanation: Use static classes only when the class is stateless and only for utility functions.

12. Prefer Composition Over Inheritance

Bad Code

C#
public class Animal
{
    public void Eat() { }
    public void Sleep() { }
}
public class Dog : Animal
{
    public void Bark() { }
}

Good Code

C#
public class Animal
{
    public void Eat() { }
    public void Sleep() { }
}
public class Dog
{
    private readonly Animal _animal = new Animal();
    public void Bark() { }
    public void Eat() { _animal.Eat(); }
    public void Sleep() { _animal.Sleep(); }
}

Explanation: Composition is often more flexible and easier to manage than inheritance.

Conclusion

Applying these clean code principles can significantly improve the quality of your code, making it easier to read, maintain, and extend. Remember, writing clean code is a continuous practice, and these tips are a good starting point to help you on that journey.