Blog
Mert Özen's blog posts on software development, backend, frontend, and DevOps.
Why Design Principles Exist: Change, Dependencies and a Short History of SOLID
Design principles exist to name the unplanned dependencies that make change expensive and to draw boundaries around them: rigidity, fragility, immobility and viscosity share dependency as their root. The history from Parnas's information hiding to Feathers's SOLID acronym, and the series' Bookstore order and notification example.
Money and Rounding: decimal, a Money Value Object, VAT and Distributing Cents
Modeling money correctly takes a Money value object that carries the amount with its currency, the same explicit rounding rule in C# and SQL, and Allocate instead of division so no cent is lost. The post shows Math.Round and SQL ROUND disagreeing on 0.125, the 1-cent difference between per-line and total VAT, an effective-dated VAT rate table (20%, 10%, 1% as of November 2026), EF Core complex type mapping and string amounts in JSON, with real output.
Upgrading C# and .NET: Moving an Old Project to .NET 10
Moving a .NET 6 project to .NET 10: the support calendar, how LangVersion relates to the TFM and the latest trap, pinning the SDK with global.json, reading the real CS8981 and CS9258 warnings, the silent behavior change of the field keyword and reading breaking-change pages; C# 15 gets its own post.
What's New in C# 14: Extension Members, field and Null-Conditional Assignment
C# 14 next to its C# 10 and C# 13 equivalents: null-conditional assignment skipping the right-hand side, extension properties, static extension members and extension operators, the field keyword, arrays converting to spans, nameof(List<>), lambda parameter modifiers, partial constructors/events and compound assignment operators.
What's New in C# 13: params Collections, Lock and Partial Properties
C# 13 next to its C# 10 equivalents: the new Lock type and the CS9216 trap, params collections with an allocation measurement, ref structs implementing interfaces and allows ref struct, partial properties, OverloadResolutionPriority, the \e escape and ^ indexes in initializers.
What's New in C# 12: Primary Constructors and Collection Expressions
C# 12 next to its C# 10 equivalents: why a primary constructor is a parameter rather than a property and the CS9124 warning, square-bracket collection expressions and spread, default lambda parameters, alias any type, inline arrays, the Experimental attribute and a note on interceptors.
What's New in C# 11: Raw Strings, required and List Patterns
How we wrote it in C# 10 and how we write it in C# 11: raw string literals and the culture trap, required members and SetsRequiredMembers, list patterns, generic math with its language and library legs, file-local types and UTF-8 literals.
C# Versions: A Short History from 1.0 to 10
The signature features, release dates and .NET pairings of every version from C# 1.0 to C# 10; compiling the same code with different LangVersion values to see how the compiler tells you which feature came from which version.
Unit Testing in C#: xUnit, Theory/InlineData and Testable Code
The hidden dependencies behind a flaky test, an xUnit test project, Fact and Assert, Theory/InlineData/MemberData, taking time from outside with IClock, and pitfalls like decimal InlineData and async void.
Dependency Injection Basics in C#: Lifetimes, the Container and Captive Dependencies
Constructor injection with Microsoft.Extensions.DependencyInjection, singleton/scoped/transient, the container's disposal duty, captive dependencies and ValidateScopes, multiple registrations, TryAdd and factories.
Performance in C#: Allocations, Structs and Measuring with BenchmarkDotNet
Why Stopwatch isn't enough, setting up BenchmarkDotNet 0.15.8 and reading its table, the measured difference between classes and structs, hidden allocations from boxing and closures, and benchmark pitfalls.
Source Generators in C#: Generating Code at Compile Time with IIncrementalGenerator
Writing an incremental generator that adds code during the build: the netstandard2.0 project and Roslyn version, the pipeline and caching, seeing the generated code, and the partial and hint name pitfalls.