- Published on
Modern .NET 2026 Deep Dive — .NET 9 · C# 13 · F# 9 · ASP.NET Core · Blazor United · MAUI · Aspire · EF Core 9
- Authors

- Name
- Youngju Kim
- @fjvbn20031
Prologue — In 2026, .NET Is No Longer "Java for Windows"
Through the 2010s the view of .NET was simple. "The Microsoft stack — IIS on Windows Server with C# on top." The destination wasn't "places that could not afford Java licenses," it was "places that ran a Windows e-commerce site."
In 2026 that picture is completely different.
- Cross-platform by default — Linux, macOS, iOS, Android, WebAssembly, embedded — the same code runs everywhere.
- AOT is mainstream — one
dotnet publish -p:PublishAot=trueline gives you an 8 MB single binary. - Free and open source — .NET itself is MIT-licensed and developed on GitHub.
- First-class cloud citizen — AWS Lambda, Google Cloud Run, Azure App Service all give it tier-one support.
.NET 9 shipped in November 2024 as STS (Standard Term Support, 18 months) and .NET 10 shipped in November 2025 as LTS (Long Term Support, 36 months). As of May 2026, new projects almost all settle on .NET 10, and .NET 9 is the intermediate stop on a migration path.
This article walks the 2026 .NET stack end to end. Runtime, languages, web, UI, data, distributed, games, testing — and the matrix for picking which library where.
Chapter 1 · The .NET Runtime — STS and LTS Cycles
.NET ships an LTS every two years. Even years are LTS, odd years are STS.
- .NET 6 (Nov 2021, LTS) — EOL Nov 2024
- .NET 7 (Nov 2022, STS) — EOL May 2024
- .NET 8 (Nov 2023, LTS) — EOL Nov 2026
- .NET 9 (Nov 2024, STS) — EOL May 2026
- .NET 10 (Nov 2025, LTS) — EOL Nov 2028
.NET 9 support ended in May 2026. The right answer for a new project is to start on .NET 10. .NET 8 LTS lives until November.
# Check installed SDKs
dotnet --list-sdks
# Install .NET 10 (macOS Homebrew)
brew install --cask dotnet-sdk
# Pin a version with global.json
cat > global.json <<EOF
{
"sdk": {
"version": "10.0.100",
"rollForward": "latestFeature"
}
}
EOF
# New project
dotnet new console -n HelloWorld
cd HelloWorld
dotnet run
The runtime story has three keywords.
- CoreCLR — the JIT compiler, the main runtime. First-class on ARM64, x64, and Apple Silicon.
- Mono — the lightweight runtime used on WebAssembly, iOS, and Android.
- NativeAOT — ahead-of-time, no JIT, a single native binary. .NET 10 ships full ASP.NET Core support.
The one-line takeaway: ".NET 10 is the LTS alive until 2028, .NET 9 is the STS that ended in May 2026."
Chapter 2 · C# 13 — params Collections, lock Objects, partial Members
C# 13 shipped with .NET 9 and changed daily code. The big three:
params collections — the params parameter no longer requires an array. It accepts IEnumerable, Span, ReadOnlySpan, any collection type.
// C# 12 and earlier — params object[] only
void Log(params object[] args) { }
// C# 13 — params ReadOnlySpan<object>
void Log(params ReadOnlySpan<object> args)
{
foreach (var arg in args)
Console.WriteLine(arg);
}
// No array allocation on call. Span is stack-allocated.
Log("hello", 42, DateTime.Now);
lock object — the lock keyword now accepts a new System.Threading.Lock type. It is about 30% faster than the older lock(obj) and the compiler catches misuse.
using System.Threading;
public class Counter
{
private readonly Lock _lock = new();
private int _count;
public void Increment()
{
lock (_lock)
{
_count++;
}
}
}
partial properties and indexers — partial extends from methods to properties and indexers. Source generators get more powerful.
public partial class ViewModel
{
public partial string Name { get; set; }
}
// In another file, a source generator provides the implementation
public partial class ViewModel
{
private string _name = "";
public partial string Name
{
get => _name;
set { _name = value; OnPropertyChanged(); }
}
}
Escape sequence — \e was added for the ESC character (0x1B). Cleaner ANSI color code authoring.
Console.WriteLine("\e[31mRed text\e[0m");
C# 14 shipped alongside .NET 10. The big three new features are the field keyword (referring to the backing field of an auto-property), partial constructors, and extension members (extension everything).
Chapter 3 · F# 9 / F# 10 — Functional, AI-Friendly, Pragmatic
F# is Microsoft's ML-family functional language. On top of .NET it reads close to OCaml.
In 2026 F# gets a second look for two reasons.
- AI code-generation friendly — F# is expression-based, so LLMs can emit short and correct code.
- Data processing and finance — Jet, Bank of America, and several Korean financial firms run real F# in production.
F# 9 highlights: computation-expression improvements, nullness analysis, cleaner diagnostics. F# 10 shipped alongside .NET 10.
The smallest F# example — Fibonacci.
let rec fib n =
match n with
| 0 | 1 -> n
| _ -> fib (n - 1) + fib (n - 2)
[0..10]
|> List.map fib
|> List.iter (printfn "%d")
Records and discriminated unions are the heart of F#.
type Shape =
| Circle of radius: float
| Rectangle of width: float * height: float
| Triangle of a: float * b: float * c: float
let area shape =
match shape with
| Circle r -> System.Math.PI * r * r
| Rectangle (w, h) -> w * h
| Triangle (a, b, c) ->
let s = (a + b + c) / 2.0
sqrt (s * (s - a) * (s - b) * (s - c))
printfn "%f" (area (Circle 5.0))
F# has a REPL via dotnet fsi. It also runs as a .NET Interactive kernel in Jupyter.
Chapter 4 · VB.NET — Maintenance Mode, Not Dead Yet
Visual Basic .NET is in "maintenance mode" per Microsoft's official statement. No new language features go in, but it keeps running on the .NET runtime.
- Windows Forms, WPF, and console apps still build with VB.NET.
- New C# features (records,
initsetters, expanded pattern matching) do not land in VB.NET. - Existing codebases keep compiling, keep running, and keep getting security updates.
There is almost no reason to start a new VB.NET project in 2026. But if a 20-year-old ASP.NET Web Forms system is VB.NET, the migration cost is still there.
Chapter 5 · ASP.NET Core 10 — Minimal API, Native AOT
ASP.NET Core is the web framework on top of .NET. Two patterns have been standard since .NET 6:
- Minimal API — Express-like route declarations in a single file.
- MVC / Razor Pages — full-stack with controllers, views, and models.
The smallest Minimal API.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "Hello, World!");
app.MapGet("/hello/{name}", (string name) => $"Hello, {name}!");
app.MapPost("/items", (Item item) => Results.Created($"/items/{item.Id}", item));
app.Run();
record Item(int Id, string Name);
The big change in ASP.NET Core 10 is Native AOT. Cold start under 100 ms, memory halved, a single 10 MB binary.
dotnet publish -c Release -p:PublishAot=true
# bin/Release/net10.0/<rid>/publish/MyApi (single binary)
AOT has clear constraints. Reflection, dynamic code, and Expression.Compile() are off-limits. Instead, source generators emit code at compile time. System.Text.Json also runs on a source generator path.
[JsonSerializable(typeof(User))]
public partial class AppJsonContext : JsonSerializerContext { }
// AOT-friendly serialization
var json = JsonSerializer.Serialize(user, AppJsonContext.Default.User);
Chapter 6 · Blazor United — Server · WASM · SSR in One
Blazor is the framework for writing SPAs in C#. The three core modes in 2026, plus the "United" pattern that blends them.
- Server — UI events go to the server over SignalR; only DOM diffs come back to the client. Fast first paint, persistent connection required.
- WebAssembly — C# code is compiled to WASM and runs directly in the browser. Offline-capable, large initial download.
- SSR (Static Server Rendering) — server renders HTML only, no interactivity. SEO and landing pages.
Starting with .NET 8 you can mix all three per page in one project.
@page "/counter"
@rendermode InteractiveServer
<h1>Counter</h1>
<p>Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@code {
private int currentCount = 0;
private void IncrementCount() => currentCount++;
}
Swap @rendermode between InteractiveServer, InteractiveWebAssembly, and InteractiveAuto and the same component runs in different environments. InteractiveAuto starts Server-side and automatically switches to the client once the WASM bundle loads.
Key points:
- Component model — similar to React and Vue, but in C#.
- JS Interop — call JS only when needed via
IJSRuntime. - AOT WASM —
<RunAOTCompilation>true</RunAOTCompilation>enables WASM AOT, roughly 2x performance.
Chapter 7 · .NET MAUI 9 — iOS · Android · macOS · Windows in One
MAUI (Multi-platform App UI) is the successor to Xamarin.Forms. As of May 2026 Xamarin.Forms is officially EOL (May 2024) and every new mobile project is on MAUI.
dotnet new maui -n MyApp
cd MyApp
# iOS
dotnet build -t:Run -f net10.0-ios
# Android
dotnet build -t:Run -f net10.0-android
# macOS
dotnet build -t:Run -f net10.0-maccatalyst
# Windows
dotnet build -t:Run -f net10.0-windows10.0.19041.0
The smallest XAML page.
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MyApp.MainPage">
<VerticalStackLayout Padding="20" Spacing="10">
<Label Text="Hello, MAUI!" FontSize="32" />
<Button Text="Click me" Clicked="OnClicked" />
<Label x:Name="CounterLabel" Text="0" />
</VerticalStackLayout>
</ContentPage>
public partial class MainPage : ContentPage
{
int count = 0;
public MainPage() { InitializeComponent(); }
void OnClicked(object sender, EventArgs e)
{
count++;
CounterLabel.Text = count.ToString();
}
}
MAUI 9 highlights:
- Native controls — real native widgets on each platform. UIKit on iOS, Material on Android.
- Hot Reload — both XAML and C# hot-reload.
- MVU — a Comet-style MVU (Model-View-Update) pattern is also in trial.
The weakness has to be admitted honestly. iOS and Android are first-class, but the community ecosystem does not match React Native or Flutter. Internal corporate apps in Korea and Japan, and existing Xamarin migrations, are the main market.
Chapter 8 · Avalonia 11 · Uno Platform 5 — Community Alternatives
Two .NET UI frameworks not built by Microsoft are also strong in 2026.
Avalonia 11 — XAML-based UI running on Linux, macOS, Windows, iOS, Android, and WebAssembly. JetBrains Rider builds parts of its UI on Avalonia.
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="HelloAvalonia.MainWindow"
Title="HelloAvalonia">
<StackPanel Margin="20">
<TextBlock Text="Hello from Avalonia!" FontSize="24" />
<Button Content="Click me" Click="OnClick" />
</StackPanel>
</Window>
Uno Platform 5 — reuses WinUI 3 XAML across every platform. WebAssembly and Skia rendering are also supported. Pick this when a Windows-centric developer wants to write once and ship to several OSes.
Differences from MAUI:
- MAUI — Microsoft official, native controls, Android · iOS · Windows · macOS only.
- Avalonia — community, self-rendering (Skia), Linux first-class, strong on desktop.
- Uno — community, WinUI XAML compatible, strong on WebAssembly.
Chapter 9 · .NET Aspire 9 — Distributed App Orchestration
Aspire is the distributed-app framework that shipped with .NET 8. The core idea: "bundle several services in one solution, bring them up with one command, watch them from one dashboard."
// AppHost/Program.cs
var builder = DistributedApplication.CreateBuilder(args);
var redis = builder.AddRedis("cache");
var postgres = builder.AddPostgres("db").AddDatabase("appdb");
var api = builder.AddProject<Projects.MyApi>("api")
.WithReference(redis)
.WithReference(postgres);
builder.AddProject<Projects.MyWeb>("web")
.WithReference(api);
builder.Build().Run();
dotnet run --project AppHost
# Open https://localhost:17000 in a browser — Aspire Dashboard
What the Aspire Dashboard shows:
- Service list — per-process status, logs, environment variables.
- Traces — OpenTelemetry-based distributed tracing.
- Metrics — memory, CPU, request count.
- Log aggregation — search every service log from one place.
New in Aspire 9: stronger integration modules (Azure Service Bus, Postgres, MongoDB, Kafka), GitHub Codespaces support, and auto-generated deployment manifests (Helm, Bicep).
The one-line takeaway: "If docker-compose is the docker-compose for containers, Aspire is the docker-compose for .NET services."
Chapter 10 · Entity Framework Core 9 — JSON, Compiled Models
EF Core is the .NET world's standard ORM. The big changes in 9.0:
- Stronger JSON columns — query Postgres and SQL Server JSON columns directly with LINQ.
- Compiled model — model metadata generation moves from startup time to compile time.
- HierarchyId — SQL Server's hierarchy type via LINQ.
- Cosmos DB improvements — partial updates, hierarchical partition keys.
public class Blog
{
public int Id { get; set; }
public string Name { get; set; } = "";
public BlogMetadata Metadata { get; set; } = new();
}
public class BlogMetadata
{
public string Author { get; set; } = "";
public List<string> Tags { get; set; } = new();
}
public class BloggingContext : DbContext
{
public DbSet<Blog> Blogs => Set<Blog>();
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Blog>().OwnsOne(b => b.Metadata, b => b.ToJson());
}
}
// Query fields inside the JSON via LINQ
var blogs = await db.Blogs
.Where(b => b.Metadata.Tags.Contains("dotnet"))
.ToListAsync();
Migrations are managed with dotnet ef migrations add and dotnet ef database update.
dotnet tool install --global dotnet-ef
dotnet ef migrations add InitialCreate
dotnet ef database update
Chapter 11 · Dapper 3 · Marten — Lightweight Alternatives
If EF Core is a full ORM, Dapper is a micro-ORM. You write SQL directly and only the result mapping is automated.
using Dapper;
using Npgsql;
await using var conn = new NpgsqlConnection(connStr);
var users = await conn.QueryAsync<User>(
"SELECT id, name FROM users WHERE active = @active",
new { active = true });
foreach (var u in users)
Console.WriteLine($"{u.Id}: {u.Name}");
When to use it: hot-path queries, complex SQL, situations where the EF Core abstraction gets in the way.
Marten — Postgres as a document DB plus event store. Strong fit for CQRS and event sourcing.
var store = DocumentStore.For(opts =>
{
opts.Connection(connStr);
opts.Events.AddEventType(typeof(OrderPlaced));
});
await using var session = store.LightweightSession();
session.Events.Append(orderId, new OrderPlaced(orderId, items));
await session.SaveChangesAsync();
When to use it: environments where Postgres is already present, domains that need event sourcing.
Chapter 12 · MediatR 13 — CQRS Pattern
MediatR is an in-process mediator-pattern library. It cleanly separates handlers, notifications, and pipeline behaviors.
public record GetUserById(int Id) : IRequest<User>;
public class GetUserByIdHandler : IRequestHandler<GetUserById, User>
{
private readonly AppDbContext _db;
public GetUserByIdHandler(AppDbContext db) { _db = db; }
public async Task<User> Handle(GetUserById req, CancellationToken ct)
{
return await _db.Users.FindAsync(new object[] { req.Id }, ct)
?? throw new KeyNotFoundException();
}
}
// Controller
public class UsersController(IMediator mediator) : ControllerBase
{
[HttpGet("{id}")]
public Task<User> Get(int id) => mediator.Send(new GetUserById(id));
}
In late 2024 the author Jimmy Bogard announced commercialization of MediatR, and part of the community forked alternatives (e.g. Brighter, Mediator.SourceGenerator). So in 2026 a new project has to decide whether to stay on MediatR or move to a source-generator-based alternative.
Chapter 13 · Orleans 9 — Virtual Actors, Grain-Based Distribution
Orleans is the distributed actor framework from Microsoft Research. The virtual actor model is the core idea: grains are identified by ID and the runtime manages their location.
public interface IUserGrain : IGrainWithIntegerKey
{
Task<string> GetNameAsync();
Task SetNameAsync(string name);
}
public class UserGrain : Grain, IUserGrain
{
private string _name = "";
public Task<string> GetNameAsync() => Task.FromResult(_name);
public Task SetNameAsync(string name) { _name = name; return Task.CompletedTask; }
}
// Client
var user = client.GetGrain<IUserGrain>(123);
await user.SetNameAsync("Alice");
var name = await user.GetNameAsync();
When to use it: game backends (Halo, Forza, Gears of War are on Orleans), IoT, chat, real-time multiplayer.
Alternative: Akka.NET 1.5 — the .NET port of Akka, explicit actor model, with persistence and clustering.
Chapter 14 · SignalR · gRPC — Real-time Communication
SignalR — bidirectional real-time. It negotiates WebSocket, Server-Sent Events, and long polling automatically.
public class ChatHub : Hub
{
public async Task SendMessage(string user, string message)
{
await Clients.All.SendAsync("ReceiveMessage", user, message);
}
}
// Program.cs
builder.Services.AddSignalR();
app.MapHub<ChatHub>("/chathub");
Clients exist for JS, .NET, Java, and Python.
gRPC for .NET — protobuf-based RPC. Strong for service-to-service and polyglot environments.
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply);
}
message HelloRequest { string name = 1; }
message HelloReply { string message = 1; }
public class GreeterService : Greeter.GreeterBase
{
public override Task<HelloReply> SayHello(HelloRequest req, ServerCallContext ctx)
{
return Task.FromResult(new HelloReply { Message = $"Hello {req.Name}" });
}
}
When to use it: internal microservice communication, polyglot clients, streaming RPC.
Chapter 15 · Logging and Observability — Serilog 4, OpenTelemetry
The default is Microsoft.Extensions.Logging. Categories, filters, and scopes are built in.
public class OrderService(ILogger<OrderService> logger)
{
public void Process(Order order)
{
logger.LogInformation("Processing order {OrderId} for {Amount}",
order.Id, order.Amount);
}
}
When structured logging, file sinks, or Elasticsearch are needed: Serilog 4.
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Information()
.WriteTo.Console()
.WriteTo.File("logs/app-.txt", rollingInterval: RollingInterval.Day)
.WriteTo.Seq("http://localhost:5341")
.CreateLogger();
Log.Information("User {UserId} logged in from {IP}", userId, ip);
OpenTelemetry — the vendor-neutral standard for traces, metrics, and logs. First-class support on .NET.
builder.Services.AddOpenTelemetry()
.WithTracing(t => t
.AddAspNetCoreInstrumentation()
.AddHttpClientInstrumentation()
.AddOtlpExporter())
.WithMetrics(m => m
.AddAspNetCoreInstrumentation()
.AddRuntimeInstrumentation()
.AddOtlpExporter());
Aspire Dashboard receives OpenTelemetry and visualizes it. Jaeger, Grafana, and Datadog use the same protocol.
Chapter 16 · Testing — xUnit 3, NUnit 4, MSTest 3
Three major test frameworks, and the mocking libraries on top of them.
xUnit 3 — the most popular pick. v3 shipped in 2025. Async-friendly, clean attributes.
public class CalculatorTests
{
[Fact]
public void Add_TwoNumbers_ReturnsSum()
{
var sut = new Calculator();
Assert.Equal(5, sut.Add(2, 3));
}
[Theory]
[InlineData(1, 1, 2)]
[InlineData(2, 3, 5)]
[InlineData(-1, 1, 0)]
public void Add_Various_ReturnsExpected(int a, int b, int expected)
{
var sut = new Calculator();
Assert.Equal(expected, sut.Add(a, b));
}
}
NUnit 4 — JUnit-style. Richer attribute set.
MSTest 3 — Microsoft official, deepest Visual Studio integration.
Mocking libraries:
- Moq 4.20 — most popular, but the 2023 SponsorLink incident pushed some users away.
- NSubstitute 5 — cleaner API, gaining popularity as a Moq alternative.
- FakeItEasy 8 — foggy-object style, similar to Java's Mockito.
// NSubstitute
var repo = Substitute.For<IUserRepository>();
repo.FindById(1).Returns(new User(1, "Alice"));
var sut = new UserService(repo);
var user = sut.GetUser(1);
repo.Received(1).FindById(1);
BenchmarkDotNet 0.14 — the standard for performance microbenchmarks.
[MemoryDiagnoser]
public class StringBenchmarks
{
[Benchmark]
public string ConcatStrings()
{
var s = "";
for (var i = 0; i < 100; i++) s += i;
return s;
}
[Benchmark]
public string StringBuilder()
{
var sb = new StringBuilder();
for (var i = 0; i < 100; i++) sb.Append(i);
return sb.ToString();
}
}
BenchmarkRunner.Run<StringBenchmarks>();
Chapter 17 · Developer Experience — dotnet watch, Hot Reload, Polyglot Notebooks
dotnet watch detects file changes and rebuilds and restarts automatically.
dotnet watch run
# Edit Program.cs → auto-restart
# Edit a Razor page → hot reload (changes appear without restart)
ASP.NET Core, Blazor, and MAUI all support hot reload. Method-body changes, XAML, CSS, and Razor markup apply without restart; signature changes require a restart.
Polyglot Notebooks — Jupyter-style .NET notebooks. C#, F#, PowerShell, and SQL mix in one notebook.
dotnet tool install -g Microsoft.dotnet-interactive
dotnet interactive jupyter install
The VS Code extension (Polyglot Notebooks) opens .ipynb or .dib files. Strong for data exploration, docs, and teaching material.
// .NET notebook cell
#r "nuget: System.Text.Json"
using System.Text.Json;
var json = """{"name": "Alice", "age": 30}""";
var doc = JsonDocument.Parse(json);
display(doc.RootElement);
Chapter 18 · Build Systems — dotnet CLI, MSBuild, NUKE, FAKE, Cake
The default is the dotnet CLI plus MSBuild. Most projects need nothing else.
dotnet new sln -n MySolution
dotnet new classlib -n MyLibrary
dotnet sln add MyLibrary
dotnet build
dotnet test
dotnet pack
dotnet nuget push -s nuget.org -k <api-key>
When CI/CD pipelines grow complex, pick one of three:
- NUKE — write build scripts in C#. Type-safe, IDE autocomplete, debuggable.
- Cake —
.cakescript files, C#-like DSL. - FAKE — F# build system, functional DSL.
A NUKE example — _build/Build.cs.
class Build : NukeBuild
{
public static int Main() => Execute<Build>(x => x.Compile);
Target Clean => _ => _
.Executes(() => Directory.Delete("bin", true));
Target Compile => _ => _
.DependsOn(Clean)
.Executes(() => DotNetTasks.DotNetBuild(s => s
.SetConfiguration("Release")));
Target Test => _ => _
.DependsOn(Compile)
.Executes(() => DotNetTasks.DotNetTest(s => s
.SetConfiguration("Release")
.EnableNoBuild()));
}
./build.sh test
# or
nuke test
Chapter 19 · NuGet 6.12 — Package Management
NuGet is to .NET what npm, pip, and Maven are to other ecosystems.
# Add a package
dotnet add package Serilog --version 4.0.0
# Update
dotnet add package Serilog
# Remove
dotnet remove package Serilog
# Restore
dotnet restore
Centralized version control via Directory.Packages.props:
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="Serilog" Version="4.0.0" />
<PackageVersion Include="Dapper" Version="3.0.0" />
</ItemGroup>
</Project>
Per-project files only declare PackageReference without a version. This prevents version drift in large solutions.
global.json pins the SDK version, Directory.Packages.props pins package versions. Both are standard in a monorepo.
Chapter 20 · Game Development — Unity 6, Godot, Stride
Unity 6 (released late 2024, stable through 2026) — the market-share leader. C# 13 supported. URP (Universal Render Pipeline), HDRP (High Definition Render Pipeline), and DOTS (Data-Oriented Tech Stack) are the core pillars.
using UnityEngine;
public class PlayerController : MonoBehaviour
{
[SerializeField] float speed = 5f;
Rigidbody rb;
void Start() { rb = GetComponent<Rigidbody>(); }
void Update()
{
var h = Input.GetAxis("Horizontal");
var v = Input.GetAxis("Vertical");
rb.linearVelocity = new Vector3(h, 0, v) * speed;
}
}
After the 2023 pricing fiasco Unity rolled back the policy, but trust took the hit. In 2026 Unity still dominates indie and mobile, but new projects increasingly evaluate Godot and Unreal.
Godot 4 (C#) — open-source game engine. GDScript is the primary language but the C# bindings are stable. Growing share on mobile and indie.
Stride 4 — a pure .NET game engine. Everything is written in C#. Smaller community but a workflow that feels familiar to .NET developers.
Chapter 21 · Desktop Legacy — WPF · WinForms
WPF (Windows Presentation Foundation) and WinForms are not "legacy" in 2026. Both ship updates against .NET 10 and remain the standard for Windows enterprise desktop.
// WinForms
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
var btn = new Button { Text = "Click me", Location = new Point(20, 20) };
btn.Click += (s, e) => MessageBox.Show("Hello!");
Controls.Add(btn);
}
}
WPF brings XAML, MVVM, and powerful data binding. A large share of enterprise in-house tools in Korea and Japan run on WPF.
WinUI 3 — the new UI framework for the Windows 11 era. Packaged via the Windows App SDK. MAUI Windows uses WinUI 3 under the hood.
The selection matrix:
- New Windows-only app → WinUI 3 + Windows App SDK
- Maintaining an existing WPF codebase → keep WPF
- Windows plus other OSes → MAUI or Avalonia
- Simple internal tool → WinForms (still fast and simple)
Chapter 22 · Cloud Deployment — Azure · AWS · GCP
.NET is a first-class citizen on every cloud.
Azure App Service — the most natural pick. New .NET releases land here first.
az webapp up --name myapp --runtime "DOTNETCORE:10.0"
AWS Lambda — .NET 10 runtime supported. Cold start drops below 100 ms with AOT.
public class Function
{
public async Task<APIGatewayHttpApiV2ProxyResponse> Handle(
APIGatewayHttpApiV2ProxyRequest req, ILambdaContext ctx)
{
return new APIGatewayHttpApiV2ProxyResponse
{
StatusCode = 200,
Body = $"Hello from {req.RequestContext.Http.Path}"
};
}
}
Deploy with dotnet lambda deploy-function, SAM, or CDK.
Google Cloud Run — container-based. A single Dockerfile is enough.
FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS base
WORKDIR /app
EXPOSE 8080
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
COPY . /src
WORKDIR /src
RUN dotnet publish -c Release -o /app/publish
FROM base AS final
COPY /app/publish .
ENTRYPOINT ["dotnet", "MyApi.dll"]
Aspire auto-generates manifests for all three. One dotnet run --project AppHost --publisher manifest produces K8s YAML, Bicep, and Cloud Run manifests.
Chapter 23 · Roslyn Analyzers · Source Generators
Roslyn is the C# and VB.NET compiler. It exposes the code as a tree and offers APIs to transform it.
Analyzers — inspect code at build time and emit warnings or errors. StyleCop.Analyzers and Microsoft.CodeAnalysis.NetAnalyzers are the headline examples.
dotnet add package Microsoft.CodeAnalysis.NetAnalyzers
Hundreds of rules apply automatically at build. Tune them per-rule in .editorconfig with lines like dotnet_diagnostic.CA1822.severity = error.
Source generators — produce code at compile time. AOT-friendly, a replacement for reflection.
Representative cases:
- System.Text.Json — generates serialization code via a
JsonSerializerContextsource generator. - MapperGen / Mapperly — generates DTO mapping code.
- Mediator.SourceGenerator — replaces MediatR with a source generator.
- Regex generator —
[GeneratedRegex(...)]attribute generates regex matchers.
public partial class EmailValidator
{
[GeneratedRegex(@"^[^@]+@[^@]+\.[^@]+$")]
private static partial Regex EmailRegex();
public bool IsValid(string s) => EmailRegex().IsMatch(s);
}
At build time the compiler emits the body of EmailRegex(). No runtime regex compilation cost.
Chapter 24 · Korean and Japanese .NET Communities
Korea
- .NET Dev Community Korea — Facebook and Discord.
- Microsoft Korea — Build Korea, AI Day, and 5-6 events per year.
- .NETDev Korea conference — community-driven.
- Hanbit Media, Insight Press consistently publish C# and .NET books.
Japan
- .NETラボ勉強会 — monthly Tokyo .NET meetup.
- Microsoft Tokyo Build — integrated Azure and .NET event.
- MS Tech Summit Japan — annual flagship event.
- Qiita .NET tag — largest gathering of Japanese .NET writing.
English-language resources:
- dot.net — the official site.
- Microsoft Learn — free tutorials.
- Stack Overflow / .NET tags — still the first stop for Q&A.
- r/dotnet, r/csharp — active subreddits.
- Nick Chapsas, Tim Corey, Scott Hanselman — YouTube channels.
Epilogue — The 2026 .NET Selection Matrix
If ten years ago the answer was ".NET = Windows + IIS + Visual Studio," in 2026 the answer splits.
Three lines for choosing:
- New web API → ASP.NET Core 10 + Minimal API + AOT. Wrap with Aspire when possible.
- New mobile app → MAUI 9. Xamarin is EOL — there is no reason to write new code there.
- New full-stack SPA → Blazor United (Server + WASM + SSR). If the JS ecosystem feels closer, ASP.NET Core + React.
- Data processing and finance → F# 9/10. Functional is the right fit.
- Distributed system → Orleans 9 or Akka.NET. Message-driven distribution.
- Games → Unity 6 (share), Godot 4 (open source), Stride (pure .NET).
- Windows desktop → WinUI 3 (new), WPF (existing), WinForms (simple tools).
Runtime essentials.
- .NET 10 LTS — released Nov 2025, supported through Nov 2028. Default for new projects.
- .NET 9 STS — EOL May 2026. Projects still mid-migration.
- .NET 8 LTS — EOL Nov 2026. Conservative operations.
The one-line takeaway: ".NET is no longer Java for Windows. The .NET of 2026 is a cross-platform, AOT-capable, cloud-first full-stack runtime."
Tools change every year, but the core does not. Types · powerful libraries · full-stack integration — that is what Visual Studio promised thirty years ago, and what .NET still delivers in 2026.
References
- .NET official site — https://dot.net/
- Microsoft Learn .NET — https://learn.microsoft.com/dotnet/
- .NET 10 announcement — https://devblogs.microsoft.com/dotnet/announcing-dotnet-10/
- .NET 9 announcement — https://devblogs.microsoft.com/dotnet/announcing-dotnet-9/
- C# 13 features — https://learn.microsoft.com/dotnet/csharp/whats-new/csharp-13
- C# language design — https://github.com/dotnet/csharplang
- F# language design — https://github.com/fsharp/fslang-design
- ASP.NET Core docs — https://learn.microsoft.com/aspnet/core/
- Blazor docs — https://learn.microsoft.com/aspnet/core/blazor/
- .NET MAUI — https://learn.microsoft.com/dotnet/maui/
- .NET Aspire — https://learn.microsoft.com/dotnet/aspire/
- Entity Framework Core — https://learn.microsoft.com/ef/core/
- Orleans — https://learn.microsoft.com/dotnet/orleans/
- Avalonia UI — https://avaloniaui.net/
- Uno Platform — https://platform.uno/
- Unity — https://unity.com/
- Godot — https://godotengine.org/
- Stride engine — https://www.stride3d.net/
- xUnit — https://xunit.net/
- NuGet — https://www.nuget.org/
- BenchmarkDotNet — https://benchmarkdotnet.org/
- .NET runtime repo — https://github.com/dotnet/runtime
- .NET Dev Community Korea — https://www.facebook.com/groups/dotnetdev/
- .NETラボ勉強会 — https://dotnetlab.connpass.com/
— end —