C# and .NET Modern Features
Modern C# features (C# 8-12) and .NET capabilities: nullable reference types, records, pattern matching, LINQ, async streams, minimal APIs.
Modern C# features (C# 8-12) and .NET capabilities: nullable reference types, records, pattern matching, LINQ, async streams, minimal APIs.
| Name | Version | Description | Example | Notes |
|---|---|---|---|---|
| Nullable Reference Types | C# 8.0 / .NET Core 3.0 | Compiler warnings for potential NullReferenceException: string? means nullable, string means non-nullable | string? middleName = null; string firstName = middleName ?? "Unknown"; | Enable with <Nullable>enable</Nullable> in .csproj |
| Records | C# 9.0 / .NET 5 | Immutable reference types with value equality, positional syntax, with-expressions for non-mutating updates | public record Person(string FirstName, string LastName); var p2 = p1 with { LastName = "Smith" }; | Use record class for reference semantics, record struct for value semantics |
| Pattern Matching | C# 8-12 | Type patterns, property patterns, relational patterns, list patterns for expressive conditional logic | return shape switch { Circle c => c.Radius * c.Radius * Math.PI, Rectangle r => r.Width * r.Height, _ => 0 }; | Evolves each version: C# 7 (is/switch), C# 8 (property/recursive), C# 10 (extended), C# 12 (list) |
| LINQ | C# 3.0 / .NET Framework 3.5 | Language Integrated Query: declarative data querying with deferred execution, query syntax and method syntax | var adults = people.Where(p => p.Age >= 18).Select(p => p.Name).OrderBy(n => n); | Works with any IEnumerable<T>; IQueryable<T> for remote execution (EF Core, SQL) |
| Async Streams | C# 8.0 / .NET Core 3.0 | IAsyncEnumerable<T> for asynchronous iteration over sequences, await foreach | await foreach (var item in GetItemsAsync()) { Process(item); } | Essential for paginated APIs, database queries, real-time data streams |
| Minimal APIs | .NET 6 | Simplified HTTP API building without controllers: app.MapGet("/", () => "Hello") | var app = WebApplication.Create(args); app.MapGet("/todos/{id}", (int id, TodoDb db) => db.Todos.FindAsync(id)); | Reduces boilerplate for small APIs; use for microservices, prototypes, simple backends |
| Primary Constructors | C# 12 / .NET 8 | Constructor parameters directly on class/struct declaration, accessible as instance fields | public class Person(string firstName, string lastName) { public string FullName => $"{firstName} {lastName}"; } | Reduces boilerplate; parameters are in scope for the entire class body |
| Source Generators | .NET 5 / Roslyn 3.8 | Compile-time code generation: analyze syntax trees and emit new C# source files | [GenerateSerializer] public class MyData { } // Generates serialization code at compile time | Used by System.Text.Json, EF Core, gRPC; eliminates runtime reflection overhead |
The static files are identical to what the API returns, but with no rate limit and no server round trip. Use the API when you want a query and a content type; use the files when you want to cache one document.
curl "https://yjtoon.com/api/dataset/csharp-dotnet-features?format=toon"
const res = await fetch( "https://yjtoon.com/static-data/dataset/csharp-dotnet-features.toon" ); const toon = await res.text();
Rate limit: 120 requests per minute per IP, no key and no signup. API reference →