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
177: The nameof Operator
I see this all the time when I'm reviewing code from developers who are just starting to use the nameof operator: they treat it as a "nice-to-have" shortcut for typing strings. They think, "Oh, this just saves me from typing double quotes around my variable names."
"It's just a shortcut for typing quotes"
If you think nameof is just about typing less, you're missing the entire point of why it exists. Let's look at a common pattern: validating arguments in a constructor.
public class UserProfile { public string Username { get; set; } public UserProfile(string username) { if (username == null) { // The "old" way: hardcoded string throw new ArgumentNullException("username", "Username cannot be null."); } Username = username; } }On the surface, this works. But here is where it breaks. Imagine six months from now, you realize
usernameis too generic and you rename the parameter toaccountIdentifierusing a refactoring tool. Your IDE will update the variable usage everywhere, but it will not touch the string"username"inside that exception. Now, your code is throwing anArgumentNullExceptionfor a parameter that doesn't even exist in the method signature. You've just introduced a bug that will confuse every developer who sees that error log.Refactor-proof strings via the compiler
This is where
nameofactually solves a problem. Instead of passing a literal string, you pass the symbol itself. The compiler then converts that symbol into its string representation during the build process.public UserProfile(string username) { if (username == null) { // The professional way throw new ArgumentNullException(nameof(username), "Username cannot be null."); } Username = username; }Now, if you rename
usernametoaccountIdentifier, thenameof(username)expression will cause a compiler error immediately becauseusernameno longer exists. You're forced to fix it, or the code won't build. I love this because it moves a potential runtime disaster into a compile-time fix.One thing to keep in mind:
nameofis not reflection. It doesn't "look up" the name while the program is running. It happens entirely at compile time. In the final compiled IL (Intermediate Language),nameof(username)is replaced by the literal string"username". There is zero performance penalty for using it.You can use this for more than just parameters. It works for properties, classes, and methods too. For example, if you're using
INotifyPropertyChangedin a desktop app, instead of writingRaisePropertyChanged("CustomerName"), you'd writeRaisePropertyChanged(nameof(CustomerName)). It just makes your code significantly more robust against the inevitable changes that happen during a project's lifecycle.
📋 Practical Task
Fixing Fragile Validation in the OrderProcessor Class
You've been handed a legacy OrderProcessor class. The previous developer used hardcoded strings for all their error handling, and after a recent rename of several properties, the error messages are now incorrect and misleading.
Your Task: Replace all hardcoded parameter and property strings inside the ProcessOrder method with the nameof operator to ensure the code is refactor-safe.
public class OrderProcessor
{
public void ProcessOrder(Order order, string shippingAddress)
{
if (order == null)
{
// FIX THIS: Hardcoded string "order"
throw new ArgumentNullException("order");
}
if (string.IsNullOrWhiteSpace(shippingAddress))
{
// FIX THIS: Hardcoded string "shippingAddress"
throw new ArgumentException("Address is required.", "shippingAddress");
}
if (order.OrderId <= 0)
{
// FIX THIS: Hardcoded string "OrderId"
throw new InvalidOperationException($"The property { "OrderId" } must be greater than zero.");
}
Console.WriteLine($"Processing order {order.OrderId} for {shippingAddress}...");
}
}
public class Order
{
public int OrderId { get; set; }
}There are no comments for now.