C# has evolved at a blistering pace over the past few years with .NET 8, 9, and C# 12+. Whether you are preparing for technical interviews or architecting production systems, mastering these core C# pillars is indispensable.

1. Async / Await & Task Cancellation

Asynchronous code in C# frees the thread pool thread while waiting for I/O operations (database queries, HTTP calls, disk reads). Always pass a CancellationToken so long-running requests can be cancelled cleanly if the client disconnects.

AsyncExamples.cs
public async Task<UserDto> FetchUserAsync(int userId, CancellationToken ct)
{
    using var response = await _httpClient.GetAsync($"https://api.example.com/users/{userId}", ct);
    response.EnsureSuccessStatusCode();

    return await response.Content.ReadFromJsonAsync<UserDto>(cancellationToken: ct)
        ?? throw new InvalidOperationException("Failed to deserialize user.");
}

2. Expressive Pattern Matching

Pattern matching eliminates verbose if/else chains and switch statements, making state transitions and object inspection clean and type-safe.

PatternMatching.cs
public decimal CalculateDiscount(Customer customer, decimal total) => (customer, total) switch
{
    { customer: { IsVip: true }, total: > 500m } => total * 0.20m, // 20% for big VIP spenders
    { customer: { IsVip: true } }                => total * 0.10m, // 10% standard VIP
    { total: > 1000m }                           => total * 0.05m, // 5% large orders
    _                                            => 0m             // No discount
};

3. Records, Primary Constructors & Immutability

C# record types give you immutable reference types with built-in value equality, non-destructive mutation with with expressions, and concise primary constructor syntax.

Records.cs
public record Order(Guid Id, string CustomerEmail, decimal Amount, string Status);

var order1 = new Order(Guid.NewGuid(), "dev@thecodeworld.info", 99.99m, "Pending");

// Immutably create an updated copy with modified status:
var shippedOrder = order1 with { Status = "Shipped" };

4. LINQ & Deferred Execution

LINQ queries are lazily evaluated. They do not execute against the collection or database until an iterating method like .ToList(), .Count(), or a foreach loop runs.

⚠️
Avoid Multiple Enumerations: Calling .Count() followed by .FirstOrDefault() on an IEnumerable can re-run queries twice. Materialize with .ToList() or .ToArray() first if reused.
← Previous Guide ASP.NET Core Web API Architecture Next Guide → React Project Structure That Scales