Ever get an exception and don’t know which variable was null? This attribute tells you the name of the expression passed to the method. public static void Guard(bool condition, [CallerArgumentExpression(“condition”)] string msg = null) { if (!condition) throw new Exception($”Failed: {msg}”); } Guard(user.Age > 18); // Throws: “Failed: user.Age > 18”
Category: C#
C#: Reducing Visual Noise with Target-typed ‘new’ Expressions
Stop repeating yourself. If the type is already defined, you don’t need to write it twice. // Old Way List data = new List(); // Pro Way (C# 9+) List data = new(); Impact: It makes your code cleaner and easier to read, especially when dealing with complex generic types.
C#: Why You Should ‘Seal’ Your Classes for Performance
If you don’t expect a class to be inherited, use the sealed keyword. The Science: The JIT compiler can perform ‘Devirtualization’ on sealed classes. Since it knows there are no overrides, it calls methods directly instead of looking up the virtual method table (vtable). Small gains in many places lead to a much faster system.
C#: Reducing Boilerplate with Primary Constructors in C# 12
C# 12 allows you to declare constructor parameters directly in the class definition. No more private fields and assignment blocks! public class UserService(IDatabase db, ILogger logger) { public void Save() => logger.Log(“Saved to ” + db.Name); } Why? It makes your classes significantly shorter and focuses the reader’s eye on the logic, not the setup.
C#: Professional Formatting with Advanced String Interpolation
String interpolation isn’t just for variables; it’s for formatting. var price = 123.456; Console.WriteLine($”Price: {price:C2}”); // Currency: $123.46 Console.WriteLine($”Date: {DateTime.Now:dd/MM/yyyy}”); The Advantage: It keeps your code localized and prevents messy .ToString() calls everywhere.
C#: Why You Should Use ‘Records’ for DTOs and API Responses
Standard classes require boilerplate for equality checks. Records provide built-in value-based equality and immutability. public record UserDto(int Id, string Name, string Email); The Result: You get a thread-safe, memory-efficient data carrier in just one line of code. Ideal for modern API development.
C#: Simplifying Initialization with ??= Operator
How many times have you written if (x == null) x = new Y();? Modern C# makes this one line. // The shorthand _myList ??= new List(); _myList.Add(“Perfect”); Why? It’s expressive, reduces boilerplate, and makes your intent crystal clear to other developers.
C#: Reducing Nested Braces with the ‘Using Declaration’
Stop nesting your code with multiple `using` blocks. Modern C# allows a much cleaner syntax. // Old Way: 2 levels of nesting using (var stream = new FileStream(…)) { using (var reader = new StreamReader(stream)) { … } } // Pro Way: No nesting! using var stream = new FileStream(…); using var reader = new […]
C# Async/Await: The Deadlock Pattern That Haunts Every Senior Developer
โ ๏ธ The Silent Killer: Application.Hang System.Threading.Tasks.Task Status: WaitingForActivation No exceptions thrown No error logs Just… frozen forever Welcome to the deadlock nightmare. It’s 3 AM. Your app is frozen. Users are screaming. And you have NO IDEA where the problem is. The Classic Deadlock Pattern โ ๏ธ DEADLOCK CODE (Don’t Copy This!) // The code that […]
C# LINQ: The Performance Traps That Cost Us 90% Speed (And How to Fix Them)
๐ The LINQ That Killed Performance Beautifully expressive LINQ. Slow as molasses. Your elegant code processes 1000 items in 8 seconds. Production is on fire. The 3 Deadly LINQ Mistakes ๐ฃ Mistake #1: Multiple Enumeration โ SLOW (database hit 3 times!) var query = dbContext.Users.Where(u => u.IsActive); var count = query.Count(); // DB hit #1 […]
C#: Use nameof() Operator to Avoid Magic Strings
Hardcoded property names break on refactoring. nameof() generates string from code symbol safely. โ Magic String (Breaks on Rename): public class User { public string Name { get; set; } } // Later in code: if (propertyName == “Name”) // Typo-prone, breaks if User.Name renamed! โ nameof (Refactor-Safe): if (propertyName == nameof(User.Name)) // Compile-time checked! […]
C#: Use async/await All The Way – Don’t Block
Mixing async and blocking (.Result, .Wait()) causes deadlocks. Go async all the way! โ Deadlock Prone: public void DoWork() { var result = GetDataAsync().Result; // DEADLOCK risk! } public async Task GetDataAsync() { return await httpClient.GetFromJsonAsync(url); } โ Proper Async: public async Task DoWorkAsync() { var result = await GetDataAsync(); // No blocking! } public […]
C#: Use using Statement for Automatic Resource Disposal
Forgetting to dispose resources causes memory leaks. using statement guarantees disposal even if exception occurs. โ Manual Disposal (Risky): var stream = File.OpenRead(“file.txt”); // If exception here, stream never closed! var data = ReadData(stream); stream.Dispose(); โ Automatic (Safe): using (var stream = File.OpenRead(“file.txt”)) { var data = ReadData(stream); } // stream.Dispose() called automatically, even on […]
C#: Use StringBuilder for String Concatenation in Loops
String concatenation in loops creates tons of objects. StringBuilder is 100x faster. โ Slow (String Concat): string result = “”; for (int i = 0; i < 10000; i++) { result += i.ToString(); // Creates new string each time! } // 10,000 string objects created = slow + GC pressure โ Fast (StringBuilder): var sb […]
C#: Moving from Runtime Reflection to Build-Time Source Generators
Reflection is slow and not AOT-friendly. Source Generators allow you to generate code during the build process, making your apps faster and ready for Native AOT (Ahead-of-Time) compilation.
C#: Professional Dependency Injection – Avoiding Captive Dependencies
A ‘Captive Dependency’ happens when a Singleton service depends on a Scoped service. This can lead to memory leaks and incorrect state. Learn how to use IServiceScopeFactory to handle this correctly.
C#: Achieving Zero-Allocation Parsing with Span and ReadOnlySpan
If you process large strings or byte arrays, Substring() creates new objects on the heap. Span<T> provides a window into the memory without copying it. Impact: Massive reduction in Garbage Collection (GC) pressure for high-traffic apps.
C#: Don’t Guess, Measure with BenchmarkDotNet
Think StringBuilder is always faster? Measure it. BenchmarkDotNet is the gold standard for performance testing in the .NET ecosystem.
C#: Clean Your Files with Global Usings and File-Scoped Namespaces
Stop wasting the first 20 lines of every file on using statements. Create a GlobalUsings.cs file! global using System.Collections.Generic; global using Microsoft.Extensions.Logging;
C#: Master System.Threading.Channels for Producer-Consumer Patterns
When you have a fast data producer and a slow consumer, use Channels. It’s much faster and thread-safe than using ConcurrentQueue with locks.
C#: Speed Up Your App with Source Generators
Stop using Reflection at runtime. Source Generators create code during compilation, moving the work from the user’s CPU to the developer’s build time.
C#: Save Memory with ValueTask in High-Throughput Scenarios
If your async method often returns synchronously (like from a cache), using ValueTask instead of Task prevents an unnecessary object allocation on the heap.
C#: Why You Should Use ‘Records’ for Data Objects
Records provide built-in immutability and value-based equality, which is much safer for multi-threaded apps. public record User(int Id, string Name);
C#: Simplify Logic with Modern Switch Pattern Matching
Replace long if-else blocks with clean switch expressions. var message = status switch { 200 => “OK”, 404 => “Not Found”, _ => “Unknown” };
C#: Why Dapper is Often Better than Entity Framework
EF is great, but Dapper is the ‘King of Speed’. Use it for high-performance read queries where every millisecond counts. var users = connection.Query(“SELECT * FROM Users WHERE Active = 1”).ToList();
C#: Use ‘yield return’ for Memory Efficient Iteration
Don’t create giant lists in memory if you only need to iterate once. yield return creates items lazily. public IEnumerable GetBigData() { for(int i=0; i < 1000000; i++) yield return i; }
C#: Use Utf8JsonReader for Maximum JSON Parsing Performance
JsonSerializer.Deserialize is convenient but allocates. Utf8JsonReader parses JSON with zero allocation. Standard Way (Allocates): var user = JsonSerializer.Deserialize(json); // Creates User object + all strings + intermediates Utf8JsonReader (Zero-Allocation): using System.Text.Json; var reader = new Utf8JsonReader(jsonBytes); string name = null; int age = 0; while (reader.Read()) { if (reader.TokenType == JsonTokenType.PropertyName) { var propertyName = […]
C#: Use Local Functions for Helper Methods That Don’t Need Class Scope
Private helper methods used by only one method pollute class scope. Local functions keep helpers truly local. Without Local Function: public class Calculator { public int Calculate(int[] numbers) { var valid = FilterValid(numbers); return Sum(valid); } private int[] FilterValid(int[] numbers) => numbers.Where(n => n > 0).ToArray(); private int Sum(int[] numbers) => numbers.Sum(); // These helpers […]
C#: Use Expression-Bodied Members for Concise Property and Method Syntax
Full method/property syntax is verbose for simple operations. Expression-bodied members reduce boilerplate. Properties: // Old way public string FullName { get { return FirstName + ” ” + LastName; } } // Expression-bodied (C# 6+) public string FullName => FirstName + ” ” + LastName; Methods: // Old way public int Add(int a, int b) […]
C#: Use Channels for Producer-Consumer Patterns
BlockingCollection works but Channels provide modern async producer-consumer with backpressure support. Setup: using System.Threading.Channels; // Create channel with capacity var channel = Channel.CreateBounded(100); Producer: async Task ProduceAsync(ChannelWriter writer) { for (int i = 0; i < 1000; i++) { await writer.WriteAsync($"Item {i}"); await Task.Delay(10); } writer.Complete(); // Signal no more items } Consumer: async Task […]























