C# Exception Handling
C# File I/O
C# Delegates and Events
C# Generics
C# Async Programming
C# Best Practices

C# Best Practices

Writing maintainable, performant, and idiomatic C# code.

1 - Naming Conventions

  • PascalCase — classes, methods, properties, public fields: BankAccount, GetBalance()
  • camelCase — parameters, local variables: firstName, itemCount
  • _camelCase — private fields: _balance, _logger
  • I prefix — interfaces: ILogger, IRepository<T>
  • Async suffix — async methods: GetDataAsync(), SaveAsync()

2 - Use Modern C# Features

// Records for immutable data
public record UserDto(int Id, string Name, string Email);

// Primary constructors (C# 12)
public class Service(ILogger logger, IRepository repo)
{
    public async Task DoWorkAsync() => logger.LogInformation("Working...");
}

// Collection expressions (C# 12)
int[] numbers = [1, 2, 3, 4, 5];
List<string> names = ["Alice", "Bob"];

3 - Dispose Pattern

public class ResourceManager : IDisposable
{
    private bool _disposed = false;
    private StreamReader _reader;

    public ResourceManager(string path) => _reader = new StreamReader(path);

    public void Dispose()
    {
        if (!_disposed)
        {
            _reader.Dispose();
            _disposed = true;
        }
    }
}

using var rm = new ResourceManager("data.txt"); // auto-disposed

4 - SOLID Principles

  • Single Responsibility — one class, one reason to change
  • Open/Closed — open for extension, closed for modification
  • Liskov Substitution — subtypes must be substitutable for base types
  • Interface Segregation — many specific interfaces over one general one
  • Dependency Inversion — depend on abstractions, not concretions

Note: Enable <Nullable>enable</Nullable>, <ImplicitUsings>enable</ImplicitUsings>, and set <LangVersion>latest</LangVersion> in every new C# project. These three settings alone eliminate hundreds of lines of boilerplate and whole categories of bugs.

-Tip-