void Log(IFormattable value) Passing structs through interfaces causes boxing. Fix Use generics: void Log<T>(T value) where T : IFormattable Result: zero allocations, faster execution.
Category: C#
C# — WeakReference Prevents Hidden Memory Leaks
Event subscriptions can keep objects alive forever. var weak = new WeakReference<MyService>(service); Use case Caching Event listeners Plugin systems Prevents objects from surviving longer than intended.
C# — ArrayPool: Stop Allocating, Start Reusing
Allocating large arrays repeatedly kills performance. var pool = ArrayPool<byte>.Shared; var buffer = pool.Rent(4096); // use buffer pool.Return(buffer); Why this matters Reduces GC pressure dramatically Ideal for serializers, streams, IO-heavy code Used internally by ASP.NET Core ⚠ Always return the array — leaks are silent.
Request Body Can Only Be Read Once
Middleware reading body breaks controllers. ✅ Fix Enable buffering: context.Request.EnableBuffering(); Then rewind stream.
Scoped Services Inside Singleton = Time Bomb
public class MySingleton { public MySingleton(MyScopedService s) { } } ❌ Problem Captures first request scope forever Causes stale data & memory leaks ✅ Fix Use IServiceScopeFactory.
Expression Trees Can Kill Startup Time
Heavy use of expression compilation: Expression<Func<T, bool>> ❌ Cost JIT + dynamic method generation Slow cold starts ✅ Fix Cache compiled expressions aggressively.
Why lock(this) Can Deadlock Your Entire App
lock(this) { // work } Hidden problem External code can lock the same instance Causes unpredictable deadlocks ✅ Correct private readonly object _lock = new(); lock (_lock) { }
GC.AllocateUninitializedArray — Faster Arrays With a Catch
GC.AllocateUninitializedArray — Faster Arrays With a Catch Why it’s fast Skips zero-initialization Reduces CPU cycles ⚠ Danger Memory contains garbage values Must fully overwrite before use Use case High-performance serializers, buffers, pipelines.
Equals() Without GetHashCode() Breaks HashSets
Overriding only Equals() is a bug factory. public override bool Equals(object obj) { … } ❌ Missing: public override int GetHashCode() { … } Result HashSet duplicates Dictionary lookups fail silently
Why Dictionary Suddenly Becomes Slow
The hidden killer: rehashing. When capacity grows, the dictionary reallocates everything. ✅ Fix Always pre-size: var dict = new Dictionary<int, User>(expectedCount); Real impact Eliminates random latency spikes Crucial in hot paths
Span — The Secret Weapon for Zero-Allocation Code
Most high-performance .NET code avoids allocations entirely. Span<char> buffer = stackalloc char[64]; Why this matters Zero GC pressure Massive performance boost in parsing & serialization Used heavily inside .NET itself ⚠ Cannot escape the method scope.
Middleware Order Can Break Security
Order matters a lot. ❌ Wrong UseEndpoints(); UseAuthentication(); ✅ Correct UseAuthentication(); UseAuthorization(); UseEndpoints();
Structs Aren’t Always Faster Than Classes
Many devs assume structs = faster. ❌ Reality Large structs copy memory Passed by value by default ✅ Rule of Thumb Small, immutable → struct Complex objects → class
LINQ ToList() — The Performance Trap
This line is expensive: var users = query.ToList(); 🧠 Why Executes immediately Loads everything into memory ✅ Better Stream or filter first: var users = query.Where(x => x.IsActive);
async void — The Exception Black Hole
This should almost never exist: async void DoWork() ❌ Why it’s dangerous Exceptions crash the process Cannot be awaited Impossible to test ✅ Correct async Task DoWorkAsync() Only valid use: event handlers.
HttpClient Socket Exhaustion — Still Happening in 2025
This is wrong: new HttpClient(); ✅ Correct builder.Services.AddHttpClient(); Why Reuses sockets Prevents random timeouts
Minimal APIs — Why Filters Replace Middleware
Middleware runs for every request. ✅ Endpoint Filter app.MapPost(“/orders”, handler) .AddEndpointFilter<AuthFilter>(); Why Faster Scoped Cleaner
ValueTask — Faster but Dangerous
ValueTask<int> GetAsync(); ⚠ Hidden traps Cannot await twice Harder debugging ✅ Rule Use only when result is usually synchronous.
ConfigureAwait(false) — When It Actually Matters
Using it everywhere is wrong. ✅ Use it when: Library code No UI / request context needed await httpClient.GetAsync(url) .ConfigureAwait(false); ❌ Avoid in: ASP.NET Core (no sync context) UI event handlers
Task.Run() in ASP.NET — The Silent Scalability Killer
This looks harmless: Task.Run(() => DoWork()); ❌ Why it breaks production Bypasses request lifecycle Ignores cancellation Starves thread pool under load ✅ Correct Pattern Use background services: public class Worker : BackgroundService { protected override async Task ExecuteAsync(CancellationToken ct) { while (!ct.IsCancellationRequested) await DoWorkAsync(ct); } }
ASP.NET Core “Request Body Already Read” — Enable Buffering
Have you ever tried to read the HttpContext.Request.Body in a middleware or a filter, only to find that your API controller receives an empty body? Or worse, your application crashes? By default, the request body is a forward-only stream. Once it’s read, the pointer reaches the end, and there’s nothing left for the next component […]
ASP.NET Core “Response Compression Not Working” — The Missing MIME Types
Compression silently fails without explicit MIME config. ✅ Fix builder.Services.AddResponseCompression(options => { options.MimeTypes = ResponseCompressionDefaults.MimeTypes .Concat(new[] { “application/json” }); });
C# Boxing Kills Performance (Without You Noticing)
This looks harmless: List<object> list = new(); list.Add(5); // boxing ✅ Fix Use generics: List<int> list = new(); Why it matters Boxing allocates memory GC pressure increases fast in loops
C# “Lock Contention” — Why lock(this) Breaks Apps
This is dangerous: lock(this) { // critical section } ❌ Why it fails External code can also lock on this Deadlocks appear randomly ✅ Correct Pattern private readonly object _sync = new(); lock (_sync) { // safe }
C# Async Streams — Stop Loading Huge Lists Into Memory
If you return large datasets like this: var data = await repository.GetAllAsync(); You already lost memory and latency. ✅ Stream Instead await foreach (var item in repository.StreamAsync()) { Process(item); } Why this is life-saving Near-zero memory footprint Faster first byte Perfect for logs, exports, ETL
ASP.NET Core Health Checks That Actually Matter
Many health checks always return OK. ❌ Useless services.AddHealthChecks(); ✅ Useful services.AddHealthChecks() .AddSqlServer(conn) .AddRedis(redisConn); Why Kubernetes and load balancers rely on this.
ASP.NET Core “Slow Startup” — Reflection Scanning Trap
Large projects often scan assemblies repeatedly. ✅ Fix Disable automatic scanning where possible and register explicitly: services.AddScoped<IService, Service>(); Why Reflection is slow at startup — especially in containers.
C# Exception Handling — The Silent Performance Killer
Exceptions are expensive.They are not flow control. ❌ try { return dict[key]; } catch { return null; } ✅ return dict.TryGetValue(key, out var value) ? value : null; Rule If it can fail often → do NOT use exceptions.
C# “foreach Is Slower Than for” — Yes, Sometimes
On List<T> this matters in tight loops. ❌ foreach (var item in list) { } ✅ Faster for (int i = 0; i < list.Count; i++) { } Why foreach creates an enumerator for is index-based and faster Use this only in hot paths, not everywhere.
C# Span — The Secret to Zero-Allocation Performance
If you manipulate strings or byte arrays heavily, this matters. ❌ Common Allocation Trap var part = input.Substring(0, 10); ✅ Zero-Allocation Alternative ReadOnlySpan<char> part = input.AsSpan(0, 10); Why this is huge No heap allocation No GC pressure Perfect for parsers and hot paths

