Loading...
Loading...
Modern C# language features for .NET 10 and C# 14. Covers primary constructors, collection expressions, the field keyword, extension members, records, pattern matching, spans, and raw string literals. Load this skill when writing any new C# code, reviewing existing code for modernization, using "modern C#", "C# 14", "primary constructor", "collection expression", "records", "pattern matching", "span", "field keyword", or "extension members". Always loaded as the baseline for all agents.
npx skill4agent add codewithmukesh/dotnet-claude-kit modern-csharprecord structSpan<T>recordreadonlyinitrequired| Feature | Usage | Example |
|---|---|---|
| Primary constructors | DI injection, eliminate field assignments | |
| Collection expressions | | |
| Records | DTOs, value objects, immutable data | |
| Small stack-allocated value types | |
| Pattern matching | Switch expressions, list/property patterns | |
| List patterns | Deconstruct arrays/lists | |
| Zero-allocation slicing | |
| Raw string literals | Multi-line SQL, JSON, XML | |
| Enforce initialization | |
| Null/type/property check | |
field// GOOD — field keyword for validation in auto-property
public class Product
{
public string Name
{
get => field;
set => field = value?.Trim() ?? throw new ArgumentNullException(nameof(value));
}
public decimal Price
{
get => field;
set => field = value >= 0 ? value : throw new ArgumentOutOfRangeException(nameof(value));
}
}fieldpublic class ProductCatalog
{
// Lazy-load on first access — no manual Lazy<T> or backing field
public IReadOnlyList<Product> Products
{
get => field ??= LoadProducts();
}
private static List<Product> LoadProducts() => /* expensive load */;
}field// INotifyPropertyChanged without manual backing fields
public class OrderViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler? PropertyChanged;
public string CustomerName
{
get => field;
set
{
if (field == value) return;
field = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(CustomerName)));
}
} = "";
public decimal Total
{
get => field;
set
{
if (field == value) return;
field = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Total)));
}
}
}extension// GOOD — extension block (shipped C# 14 syntax)
public static class OrderExtensions
{
extension(Order order)
{
public decimal TotalWithTax => order.Total * 1.2m;
public bool IsHighValue => order.Total > 1000m;
public string ToSummary() =>
$"Order #{order.Id}: {order.Total:C} ({order.Items.Count} items)";
}
// Static extension members use the type (no receiver instance)
extension(Order)
{
public static Order Empty => Order.Create("none", [], DateTimeOffset.MinValue);
}
}
// Callers see them as if declared on Order
if (order.IsHighValue) { /* ... */ }this// BAD — manual backing field when field keyword works
private string _name;
public string Name
{
get => _name;
set => _name = value ?? throw new ArgumentNullException();
}
// BAD — old-style collection initialization
var list = new List<int>() { 1, 2, 3 };
// BAD — Tuple instead of record for domain types
(string Name, decimal Price) product = ("Widget", 9.99m);
// GOOD — record
public record Product(string Name, decimal Price);// BAD — deeply nested pattern that's hard to read
if (order is { Customer: { Address: { Country: { Code: "US" } } } })
// GOOD — extract to a clear method or use sequential checks
if (order.Customer.Address.Country.Code == "US")var// BAD — what type is this?
var result = Process(order);
// GOOD — explicit type when not obvious
Result<Order> result = Process(order);
// Also GOOD — var is fine when type is apparent
var orders = new List<Order>();| Scenario | Recommendation |
|---|---|
| DTO / API contract | |
| Small value object (2-3 fields) | |
| Service with DI | Primary constructor |
| Collection creation | Collection expression |
| Property with validation | |
| Multi-line string (SQL, JSON) | Raw string literal |
| Slicing strings/arrays | |
| Type checking + extraction | Pattern matching with |
| Enforced initialization | |
| Adding methods to external types | Extension members |