Modern C# (8–13)
Records, pattern matching, nullable reference types, primary constructors, required members.
The client's stack is C# on .NET 8/9/10, so expect them to notice if you're still writing C# like it's 2015. Know these by name and be able to say why you'd reach for them, not just what they do.
Records — immutable-by-default reference (or record struct for value) types with built-in
value equality and with-expressions for non-destructive mutation. Ideal for DTOs, CQRS messages, and DDD value objects.
public record OrderPlaced(Guid OrderId, string CustomerId, decimal Total);
var original = new OrderPlaced(Guid.NewGuid(), "cust-1", 99.90m);
var corrected = original with { Total = 89.90m }; // new instance, original untouched
Pattern matching — switch expressions, property patterns, and relational patterns let you
express branching logic declaratively instead of nested ifs (this is directly relevant to the
Strategy pattern topic — pattern matching is the "quick and dirty" alternative interviewers expect
you to know and know the limits of).
double Discount(Customer c) => c switch
{
{ Type: CustomerType.Premium, YearsActive: > 5 } => 0.25,
{ Type: CustomerType.Premium } => 0.20,
{ Type: CustomerType.Regular } => 0.10,
_ => 0
};
Nullable reference types () — the compiler tracks nullability as
part of the type system and warns on unguarded dereferences. Say this explicitly if asked about null
safety: it's a compile-time analysis, not a runtime guarantee — ! (null-forgiving) bypasses it.
Primary constructors (C# 12) — constructor parameters usable directly in the class body without manually declaring fields, now valid on regular classes, not just records.
public class DiscountService(IDiscountStrategyFactory factory)
{
public double Calculate(string customerType, double price) =>
factory.GetStrategy(customerType).Calculate(price);
}
Required members (C# 11) — required properties force callers to set them via object initializer,
giving you DTO immutability-ish guarantees without a big constructor.
Flashcards (5)
record give you that a class doesn't, by default?record and record struct?<Nullable>enable</Nullable> actually enforce?switch expression with property patterns over an if/else chain?