Building strings in loops? String interpolation is clean but creates a new string on every concatenation. Here’s when to use what. The Readability Winner: // Old way – hard to read string message = “User ” + userName + ” (ID: ” + userId + “) logged in at ” + timestamp; // Modern way […]
Category: C#
LINQ Performance Trap: Why .Any() Is 10,000x Faster Than .Count() > 0
Using .Count() > 0 to check if a collection has items? You’re forcing LINQ to enumerate the entire collection just to answer a yes/no question. The Performance Killer: var users = dbContext.Users.Where(u => u.IsActive); // BAD: Counts ALL active users first if (users.Count() > 0) { Console.WriteLine(“We have active users”); } // Database query generated: […]
C# Pattern Matching: Replace Complex If-Else Chains with Switch Expressions
Nested if-else statements making your code unreadable? C# 9+ switch expressions with pattern matching can reduce 50+ lines to 10. The Old Nightmare: public decimal CalculateDiscount(Customer customer, Order order) { if (customer == null) return 0; if (customer.IsPremium) { if (order.Total > 1000) return order.Total * 0.20m; else if (order.Total > 500) return order.Total * […]
C# Records: Immutable Data Classes with Built-In Value Equality (C# 9+)
Tired of writing boilerplate Equals, GetHashCode, and ToString methods? C# records do it automatically with better performance. Old Way – Traditional Class: // BAD: 60+ lines for simple data class public class Person { public string FirstName { get; set; } public string LastName { get; set; } public int Age { get; set; } […]
C#: Async/Await Common Mistakes That Kill Performance (And How to Fix Them)
Using async/await everywhere doesn’t automatically make your code faster – it can actually make it slower if done wrong. Here are the critical mistakes. Mistake 1: Async All The Way Down (Unnecessarily): // BAD: Unnecessary async overhead public async Task GetUserIdAsync(string username) { return await Task.FromResult(_cache.Get(username)); // Why async? } // This creates a Task, […]
C# Performance: Use Span and Memory to Eliminate Array Allocations
Processing large arrays or strings eating up memory? Span<T> lets you work with slices of memory without allocating new arrays. The Problem – Traditional Approach: // BAD: Creates new array on every call public byte[] ProcessChunk(byte[] data, int start, int length) { byte[] chunk = new byte[length]; // Heap allocation Array.Copy(data, start, chunk, 0, length); […]
.NET Core: Fix Memory Leaks by Understanding IDisposable and Using Patterns
Your .NET application’s memory usage grows infinitely? You’re probably not disposing resources properly. Here’s the complete guide. The Memory Leak – Classic Example: // WRONG: Memory leak public async Task ProcessOrdersAsync() { var dbContext = new ApplicationDbContext(); var orders = await dbContext.Orders.ToListAsync(); // Process orders… // dbContext never disposed = connection stays open = memory […]
Why Exceptions Are Slower Than You Think
Exceptions are control-flow bombs. Cost Stack trace capture Heap allocations Cache pollution Rule Exceptions = exceptional cases. Alternative if (!TryParse(value, out result)) { // handle } Cause → Effect Using exceptions as logic → invisible performance debt.
The Hidden Cost of record Types in Hot Paths
Records are great.Until you overuse them. Why Value-based equality Copy semantics More allocations in loops Rule Use records for: DTOs Messages Boundaries Avoid in: Hot loops Performance-critical paths
Why async Code Can Still Block Threads
Async ≠ non-blocking by default. The trap await Task.Run(() => LongCpuWork()); You just moved blocking to the thread pool. Rule Async is for I/O, not CPU. Correct Use async APIs for I/OUse background workers for CPU
Why BackgroundServices Die Silently in Production
Looks fine locally.Stops running in prod. Root cause Unhandled exceptions inside ExecuteAsync. What actually happens The host kills the service quietly. Correct pattern protected override async Task ExecuteAsync(CancellationToken ct) { while (!ct.IsCancellationRequested) { try { await DoWork(ct); } catch (Exception ex) { logger.LogError(ex, “Background task failed”); await Task.Delay(5000, ct); } } } Cause → Effect […]
Why LINQ in Hot Paths Can Kill Performance
LINQ is elegant… and allocates. Problem Deferred execution Hidden enumerators Fix Use LINQ at boundaries, not inside loops. for (int i = 0; i < list.Count; i++) { Process(list[i]); } Why Predictable execution beats elegance under load.
Why lock(this) Is a Concurrency Time Bomb
You don’t control who else locks this. Fix private readonly object _sync = new(); lock (_sync) { } Why Encapsulation matters in threading.
Why async void Should Almost Never Exist
async void hides exceptions. Only valid Event handlers Wrong async void Process() { throw new Exception(); } Correct async Task Process()
Why Background Services Stop Without Errors
BackgroundService silently dies if an exception escapes. Rule Always wrap execution loops. while (!stoppingToken.IsCancellationRequested) { try { await DoWork(); } catch (Exception ex) { Log(ex); } } Why Unhandled exceptions kill the worker.
Why HttpClient Causes Random Timeouts
Creating HttpClient per request is a silent killer. Problem Socket exhaustion DNS caching issues Fix Use IHttpClientFactory. services.AddHttpClient(); Why It pools handlers safely.
Why foreach Is Sometimes Slower Than for
Not always — but when it matters, it matters. Reason Enumerator allocations Interface dispatch Bounds checks differ Critical paths Use for on arrays and spans. for (int i = 0; i < arr.Length; i++) { Process(arr[i]); }
The Hidden Cost of Exceptions as Flow Control
Exceptions are expensive. Bad try { Parse(input); } catch { } Better if (TryParse(input, out var result)) { … } Why Exceptions unwind stacks and allocate memory.
Why lock Can Kill Throughput
Locks serialize execution. Bad lock(_sync) { Process(); } Better Reduce lock scope Prefer immutable data Use ConcurrentDictionary Why CPU cores idle while waiting.
The Real Cost of IHostedService Misuse
Background services look harmless… until production. Common mistake Long-running loops No cancellation handling Blocking delays Correct pattern while (!stoppingToken.IsCancellationRequested) { await DoWorkAsync(stoppingToken); await Task.Delay(TimeSpan.FromSeconds(5), stoppingToken); } Why Graceful shutdowns save data and prevent zombie processes.
Why Async Controllers Still Block Threads
Async ≠ non-blocking. The trap public async Task<IActionResult> Get() { var data = _service.GetDataAsync().Result; return Ok(data); } Why it blocks .Result blocks the request thread Can cause thread starvation under load Fix var data = await _service.GetDataAsync();
Expression-Bodied Members
int Sum() => a + b; Why it mattersReadable, compact, expressive.
Span for High-Performance Parsing
Why it mattersZero allocations in hot paths.
Pattern Matching switch
return obj switch { null => 0, _ => 1 }; Why it mattersClear intent, fewer bugs.
Minimal APIs with Validation
app.MapPost(“/users”, (User u) => Results.Ok()); Why it mattersLess ceremony, same power.
with Expressions for Safe Mutations
var updated = user with { IsActive = true }; Why it mattersImmutable style without boilerplate.
Guard Clauses Improve Readability
if (user == null) return; Why it mattersFlatter code, easier reasoning.
ValueTask for Hot Paths
ValueTask<int> GetValueAsync(); Why it mattersAvoids allocations in high-frequency calls.
Use ProblemDetails for API Errors
return Results.Problem(“Invalid input”); Why it mattersStandardized error responses = better clients.
Background Tasks with IHostedService
public class Worker : BackgroundService { protected override Task ExecuteAsync(CancellationToken ct) => Task.CompletedTask; } Why it mattersClean background jobs without hacks.




