System.Text.Json is fast but MemoryPack uses binary format for extreme performance. Install: dotnet add package MemoryPack Define Serializable Type: [MemoryPackable] public partial class User { public int Id { get; set; } public string Name { get; set; } = string.Empty; public string Email { get; set; } = string.Empty; public DateTime CreatedAt { get; […]
Category: C#
C#: Use params ReadOnlySpan for Allocation-Free Variable Arguments
params arrays create heap allocation on every call. C# 13 allows params with Span for zero-allocation variable args. Old Way (Allocates): // params creates new int[] on every call public int Sum(params int[] numbers) { return numbers.Sum(); } // Called 1 million times = 1 million array allocations! Sum(1, 2, 3); New Way – C# […]
C#: Use ObjectPool for Reusing Expensive Objects
Creating and destroying heavy objects (StringBuilder, MemoryStream) repeatedly wastes memory. ObjectPool reuses them. Install: dotnet add package Microsoft.Extensions.ObjectPool Setup: // Program.cs builder.Services.AddSingleton(); builder.Services.AddSingleton(sp => { var provider = sp.GetRequiredService(); return provider.CreateStringBuilderPool(); }); Use in Service: public class TextService(ObjectPool pool) { public string BuildLargeText(IEnumerable items) { // Get StringBuilder from pool (reuse, no new allocation) var […]
C#: Use Lazy for Expensive Object Initialization
Creating expensive objects at startup wastes resources if they’re never used. Lazy defers creation until first access. Without Lazy: public class ReportService { // Created on class instantiation even if never used private readonly PdfGenerator _pdfGen = new PdfGenerator(); // Heavy! private readonly ExcelExporter _excelExporter = new ExcelExporter(); // Heavy! public void GeneratePdf() => _pdfGen.Generate(); […]
C#: Use ArgumentNullException.ThrowIfNull for Cleaner Validation
Manual null checks are verbose. C# 11 has built-in helper for cleaner validation. Old Way: public void ProcessUser(User user, string name, ILogger logger) { if (user == null) throw new ArgumentNullException(nameof(user)); if (name == null) throw new ArgumentNullException(nameof(name)); if (logger == null) throw new ArgumentNullException(nameof(logger)); // Actual logic… } New Way (C# 11): public void […]
C#: Use Discard Pattern to Ignore Unwanted Values
Variables you’ll never use clutter code. Discards (_) explicitly mark them as unused. Tuple Deconstruction: // Don’t need middle value var (first, _, last) = (“John”, “middle”, “Doe”); // Don’t need first two var (_, _, important) = GetThreeValues(); Out Parameters: // Only care if it parses, not the value if (int.TryParse(input, out _)) { […]
C#: Use Deconstruction with Tuples for Cleaner Multiple Returns
Returning multiple values via out parameters is messy. Tuples with deconstruction are clean. Old Way (out parameters): public bool TryParse(string input, out int result, out string error) { // Ugly signature, can’t use in expressions } // Usage if (TryParse(input, out int result, out string error)) { // … } Tuple Return: public (bool success, […]
C#: Use File-Scoped Types to Limit Class Visibility
Helper classes polluting your namespace? File-scoped types are only visible in their file. Problem: // HelperClass visible everywhere in project public class ProductService { // … } public class HelperClass // Only used by ProductService { // But visible to entire project! } Solution – File-Scoped Types: // ProductService.cs public class ProductService { private readonly […]
C#: Use Collection Expressions for Cleaner Collection Initialization
Creating collections with new List { } is verbose. C# 12 collection expressions simplify it. Old Way: List numbers = new List { 1, 2, 3 }; int[] array = new int[] { 1, 2, 3 }; var combined = numbers.Concat(array).ToList(); Collection Expressions: // Simpler syntax List numbers = [1, 2, 3]; int[] array = […]
C#: Use Primary Constructors to Reduce Boilerplate in Classes
Writing constructors with property assignment is repetitive. C# 12 primary constructors simplify it. Old Way: public class ProductService { private readonly ILogger _logger; private readonly IProductRepository _repo; public ProductService(ILogger logger, IProductRepository repo) { _logger = logger; _repo = repo; } public void DoWork() { _logger.LogInfo(“Working”); _repo.Save(); } } Primary Constructor (C# 12): public class ProductService(ILogger […]
C#: Use Raw String Literals for Multiline Strings Without Escaping
Escaping quotes and newlines in strings is annoying. C# 11 raw string literals handle everything. Old Way (Escape Hell): var json = “{\”name\”: \”John\”, \”age\”: 30}”; var path = “C:\\Users\\John\\Documents”; var html = ” <div class=\”container\”>Content</div>”; Raw String Literals: // Use at least 3 quotes var json = “”” { “name”: “John”, “age”: 30 } […]
C#: Use List Patterns to Match List Elements in Pattern Matching
Checking list contents with if statements is verbose. C# 11 list patterns make it clean. Traditional Way: if (numbers.Count >= 3 && numbers[0] == 1 && numbers[2] == 3) { // Do something } List Pattern: if (numbers is [1, _, 3, ..]) { // Matches list starting with 1, any value, then 3, then […]
C#: Use Pattern Matching in Property Patterns for Complex Conditions
Nested if statements for object properties are messy. Property patterns make complex checks clean. Messy If-Else: if (user != null && user.Address != null && user.Address.Country == “USA” && user.Age >= 18) { return “Eligible”; } Clean Property Pattern: var result = user switch { { Address.Country: “USA”, Age: >= 18 } => “Eligible”, { […]
C#: Use IAsyncEnumerable for Streaming Large Data Sets
Loading all results into memory first is wasteful. IAsyncEnumerable streams results as they’re retrieved. Old Way – Load Everything: public async Task GetOrdersAsync() { return await _db.Orders.ToListAsync(); // Loads all 1 million orders into memory! } // Caller: var orders = await GetOrdersAsync(); // 5GB in memory foreach (var order in orders) ProcessOrder(order); Stream with […]
C#: Use ValueTask for Async Methods That Often Return Synchronously
Task allocates even when result is immediately available. ValueTask avoids allocation for synchronous returns. Scenario: // Cache that often has value ready (no async needed) public async Task GetUserAsync(int id) { if (_cache.TryGetValue(id, out var user)) return user; // Immediate return, but still allocates Task return await _db.Users.FindAsync(id); } Better with ValueTask: public async ValueTask […]
C#: Use Span for High-Performance Array Operations
Array operations creating copies wastes memory. Span provides view over memory without copying. Traditional Array Slicing: int[] numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; int[] slice = numbers.Skip(2).Take(5).ToArray(); // Creates new array, copies 5 elements With Span: int[] numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; […]
C#: Use Tuple Deconstruction in foreach for Dictionary Iteration
Dictionary foreach with KeyValuePair is verbose. Tuple deconstruction makes it clean. Old Verbose Way: var scores = new Dictionary { [“Alice”] = 95, [“Bob”] = 87, [“Charlie”] = 92 }; foreach (KeyValuePair kvp in scores) { Console.WriteLine($”{kvp.Key}: {kvp.Value}”); } Clean Deconstruction: foreach (var (name, score) in scores) { Console.WriteLine($”{name}: {score}”); } // Or with types: […]
C#: Use var Pattern in Switch Expressions for Type Matching
Checking object types with multiple if-else is messy. Switch expressions with type patterns are cleaner. Old If-Else Chain: object obj = GetData(); if (obj is string s) { Console.WriteLine($”String: {s.Length} chars”); } else if (obj is int i) { Console.WriteLine($”Number: {i * 2}”); } else if (obj is List list) { Console.WriteLine($”List: {list.Count} items”); } […]
C#: Use init Accessor to Create Immutable Objects Without Constructor Boilerplate
Want immutable objects but constructors with 10 parameters are ugly? Use init accessors. Old Way – Constructor Overload Hell: public class Person { public string Name { get; } public int Age { get; } public string Email { get; } public Person(string name, int age, string email) { Name = name; Age = age; […]
C#: Use Index and Range Operators for Cleaner Array Slicing
Array slicing with loops or LINQ is verbose. C# 8+ has Python-like syntax. Old Way: var numbers = new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; // Get last element var last = numbers[numbers.Length – 1]; // 9 // Get last 3 elements var lastThree = numbers.Skip(numbers.Length – 3).ToArray(); // […]
C#: Use Null-Coalescing Assignment to Simplify Lazy Initialization
Checking if null before initializing is verbose. Use ??= operator for clean lazy initialization. Old Verbose Way: private List _cache; public List GetCache() { if (_cache == null) { _cache = new List(); } return _cache; } Clean Way: private List _cache; public List GetCache() { _cache ??= new List(); return _cache; } // If […]
C#: Use Target-Typed new Expressions to Reduce Verbosity
Stop repeating type names when it’s obvious from context. Use target-typed new. Verbose: Dictionary data = new Dictionary(); Person person = new Person(); List names = new List() { “John”, “Jane” }; Concise: Dictionary data = new(); Person person = new(); List names = new() { “John”, “Jane” }; Type inferred from left side. Less […]
C#: Use nameof Operator to Avoid Magic Strings
Hardcoding property names as strings breaks when you rename. Use nameof for refactor-safe code. Bad: public class Person { public string Name { get; set; } public void UpdateName(string newName) { Name = newName; OnPropertyChanged(“Name”); // Breaks if you rename property! } } Good: OnPropertyChanged(nameof(Name)); // Compiler-verified! If you rename Name property, compiler updates nameof() […]
C#: Use String Interpolation with Alignment for Formatted Output
Aligning console output without string.Format mess? String interpolation supports alignment. Basic Alignment: var name = “John”; var age = 30; Console.WriteLine($”{name,10} | {age,5}”); // Output: ” John | 30″ // Right-aligned, 10 chars for name, 5 for age Left-Align with Negative: Console.WriteLine($”{name,-10} | {age,-5}”); // Output: “John | 30 ” Combined with Formatting: var price […]
C# Record Types: Immutable Data Patterns That Eliminate Bugs
Mutable objects causing threading issues? C# 9+ records provide immutable data structures with built-in value semantics. Records vs Classes: When to Use Each // Use RECORDS for: // 1. Immutable data transfer objects (DTOs) // 2. Value objects in domain-driven design // 3. Configuration objects // 4. API request/response models // 5. Event objects in […]
C# LINQ Performance Secret: How ToQueryString() Can Reduce Database Calls by 90%
Are your Entity Framework queries making too many database trips? Discover how IQueryable.ToString() reveals the actual SQL and helps you batch queries efficiently. The Hidden Debugging Gem: // Instead of this naive approach (multiple queries) var users = db.Users.Where(u => u.IsActive).ToList(); var orders = db.Orders.Where(o => o.UserId == userId).ToList(); var products = db.Products.Where(p => p.CategoryId […]
C#: Use Source Generators to Generate Boilerplate Code at Compile Time
Writing repetitive mapping code, serialization logic, or validators? Source Generators create code at compile time, eliminating runtime reflection overhead. What Are Source Generators: // You write this: [GenerateToString] public partial class Person { public string Name { get; set; } public int Age { get; set; } } // Source Generator automatically creates this at […]
C#: Use Channels for Producer-Consumer Patterns (Better Than BlockingCollection)
Processing queue of tasks between threads? System.Threading.Channels provides async-first, high-performance producer-consumer patterns. Install Package: dotnet add package System.Threading.Channels Basic Producer-Consumer: using System.Threading.Channels; // Create unbounded channel var channel = Channel.CreateUnbounded(); // Producer task var producer = Task.Run(async () => { for (int i = 0; i < 100; i++) { await channel.Writer.WriteAsync($"Message {i}"); await Task.Delay(10); […]
C#: Use Record Types with With-Expressions for Immutable Data Transformations
Modifying objects causes bugs when multiple parts of code reference the same instance. Records with with-expressions create modified copies safely. The Mutable Class Problem: public class Person { public string Name { get; set; } public int Age { get; set; } } var person = new Person { Name = “John”, Age = 30 […]





























