C#
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Object-Oriented C#
-
Section 4: Working with Data
-
Section 5: Error Handling
-
Section 6: Delegates and Events
-
Section 7: Async Programming
-
Section 8: More Language Features
-
Section 9: File I/O and Serialization
-
Section 10: Networking in .NET
-
Section 11: The .NET Ecosystem
-
Section 12: Memory and Performance
-
Section 13: Concurrency Beyond Async
-
Section 14: Reflection and Attributes
-
Section 15: Testing and Best Practices
-
Section 16: Design Patterns in C#
-
Section 17: Standard Library Deep Dive
-
Section 18: Data Structures and Algorithms in C#
-
Section 19: GUI and Desktop Development Overview
-
Section 20: Practical Projects
-
Section 21: More Practice Exercises
-
Section 22: More Standard Library and Text Processing
-
Section 23: More Design Patterns
-
Section 24: More Projects
-
Section 25: Interview Practice
-
Section 26: C# Keywords Reference (Modifiers)
-
Section 27: C# Keywords Reference (Statements)
-
Section 28: C# Keywords Reference (Operators)
-
Section 29: BCL: System.Collections.Generic
-
Section 30: BCL: System.Linq
-
Section 31: BCL: System.Threading
-
Section 32: BCL: System.IO
-
Section 33: BCL: System.Text and System.Text.Json
-
Section 34: BCL: System.Net.Http
-
Section 35: C# Language Specification Topics
-
Section 36: More Practice Exercises
-
Section 37: More Async Patterns
-
Section 38: More BCL: System.Reflection and System.Diagnostics
-
Section 39: Nullable Reference Types In Depth
-
Section 40: C# Records and Pattern Matching In Depth
-
Section 41: Dependency Injection Deep Dive
-
Section 42: More Interview and Whiteboard Practice
179: The ?? and ??= Operators Revisited
I was looking through a legacy configuration module yesterday and noticed a pattern that made my eyes twitch. It was just a wall of if (value == null) statements used to set defaults. We've touched on null-coalescing before, but I want to show you how these operators actually feel when you're trying to clean up a real-world "settings" scenario.
Taming the null-check wall
Imagine we're building a user profile system for a code editor. Some users specify their preferred theme and font size, but most just leave them blank. If we handle this the old-fashioned way, we end up with something like this:
string userTheme = GetThemeFromDatabase();
string activeTheme;
if (userTheme != null)
{
activeTheme = userTheme;
}
else
{
activeTheme = "Dark Mode";
}
It works, sure. But it's five lines of code to do one simple thing: "Use the value if it exists, otherwise use this default." This is where the null-coalescing operator (??) makes my life easier. I can collapse that entire block into a single line:
string activeTheme = GetThemeFromDatabase() ?? "Dark Mode";
I love this because it reads almost like a sentence. "Active theme is the database value, or else 'Dark Mode'." It's clean, and it prevents me from having to declare activeTheme on one line and assign it inside a block on another.
The "Check then Assign" Loop
Now, here is where it gets interesting. Sometimes I don't just want a temporary local variable; I want to ensure that a property on an object is populated if it's currently null. I used to do this all the time:
public class UserSettings
{
public string CustomFontSize { get; set; }
}
// ... somewhere in the logic ...
var settings = new UserSettings();
if (settings.CustomFontSize == null)
{
settings.CustomFontSize = "12pt";
}
This is a common pattern: check for null, and if it is null, assign a value. But notice how I'm typing settings.CustomFontSize twice? In a complex object graph, that becomes a nightmare to read (imagine user.Account.Preferences.Display.FontSize). It's redundant.
Smoothing it out with ??=
This is exactly why C# introduced the null-coalescing assignment operator (??=). It basically says: "If the thing on the left is null, assign the thing on the right to it. If it's not null, do absolutely nothing."
Let's rewrite that settings logic:
var settings = new UserSettings();
settings.CustomFontSize ??= "12pt";
That's it. One line. If CustomFontSize already had a value (say, "14pt"), the operator sees that it's not null and just skips the assignment entirely. I've seen developers use this in constructor logic or "Lazy Initialization" patterns to make sure a list or a cache is created only when it's actually needed.
The key distinction I always keep in mind is this: ?? is for when you want to use a fallback value without necessarily changing the original variable. ??= is for when you want to fix the null variable by giving it a permanent default.
📋 Practical Task
Implementing a Game Character Stat Fallback
You are building a character sheet for an RPG. Some characters have specialized stats (like MagicPower or Stealth) that are only assigned if the character class supports them. Otherwise, they should be null. However, when calculating damage, you cannot have a null value—you need a baseline default of 0.
Create a class called Character with the following properties:
string Nameint? MagicPower(Nullable int)int? Stealth(Nullable int)
Write a method called InitializeDefaults() that uses the ??= operator to ensure that if MagicPower or Stealth are null, they are assigned a default value of 0.
Then, write a method called GetPowerLevel() that uses the ?? operator to return the sum of MagicPower and Stealth, treating them as 0 if they are null, without modifying the actual properties of the class.
There are no comments for now.