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
42: The Null-Conditional and Null-Coalescing Operators
I want to show you a piece of code that looks perfectly innocent but is actually a landmine. I see this all the time in PRs from developers who are rushing. Imagine we're building a user profile system where users can optionally provide an address.
public class User {
public string Name { get; set; }
public Address HomeAddress { get; set; }
}
public class Address {
public string City { get; set; }
}
// ... somewhere in the logic ...
User user = GetUserFromDatabase(userId);
string city = user.HomeAddress.City;
Console.WriteLine($"User lives in {city}");
The Dreaded NullReferenceException Chain
The problem here is that we're making two massive assumptions: first, that user isn't null, and second, that the user actually has a HomeAddress object assigned. If the user exists but hasn't filled out their address yet, user.HomeAddress is null. The moment you try to access .City on a null object, the runtime throws a NullReferenceException and your app crashes.
Now, you could fix this the "old way" with nested if-statements. I call this the "Pyramid of Doom" because your code starts drifting further and further to the right of the screen:
string city = "Unknown";
if (user != null) {
if (user.HomeAddress != null) {
if (user.HomeAddress.City != null) {
city = user.HomeAddress.City;
}
}
}
It works, but it's exhausting to read and write. It obscures the actual intent of the code—which is simply to get a city name or a default value if it's missing.
Short-Circuiting with the Null-Conditional Operator
This is where the null-conditional operator (?.) becomes your best friend. Think of it as a "safety check" that you can bake directly into your property access. Instead of a full if block, you just swap the dot for a question mark-dot.
// This says: "If the thing to the left is null, stop here and just return null."
string city = user?.HomeAddress?.City;
If user is null, the whole expression evaluates to null immediately. If user exists but HomeAddress is null, it also evaluates to null. It effectively "short-circuits" the chain. I love this operator because it turns five lines of boilerplate into one readable line.
Providing Defaults with Null-Coalescing
The problem now is that city is a nullable string. Often, you don't want a null value passing through your UI; you want a sensible default like "Unknown" or "Not Provided". That's where the null-coalescing operator (??) comes in.
The ?? operator says: "If the value on my left is null, use the value on my right instead." Let's combine it with the conditional operator we just learned:
string city = user?.HomeAddress?.City ?? "Unknown";
Read this as a sentence: "Try to get the city from the user's home address, but if any part of that chain is null, just give me 'Unknown'." It's clean, it's safe, and it's exactly how you should be handling optional data in modern C#.
As a side note, you might also run into the null-coalescing assignment operator (??=). This is a shorthand for assigning a value to a variable only if that variable is currently null. It's great for "lazy loading" or initializing settings:
// Only assign the default list if _cachedUsers is actually null
_cachedUsers ??= LoadUsersFromDatabase();📋 Practical Task
Building a Robust Application Settings Loader
You are tasked with creating a configuration handler for a game. The game has a GameSettings class and a VideoSettings class. Not all users have customized their video settings; many leave them as null to use the system defaults.
Your Goal: Write a method that retrieves the Resolution string. If the GameSettings object is null, or the VideoSettings object is null, or the Resolution itself is null, the method should return the string "1920x1080".
Requirements:
- Use the null-conditional operator (
?.) to navigate the object hierarchy. - Use the null-coalescing operator (
??) to provide the fallback resolution. - Do not use
ifstatements or ternary operators (? :).
public class VideoSettings {
public string Resolution { get; set; }
}
public class GameSettings {
public VideoSettings Video { get; set; }
}
public class SettingsManager {
public string GetResolution(GameSettings settings) {
// Your code here
}
}There are no comments for now.