Menu

How to Use the nameof Operator for Safer Refactoring in C#

Refactoring code can be risky, especially when dealing with hardcoded string literals representing variable, property, or method names.

One small change in a name could lead to runtime errors that are difficult to track down. Fortunately, C# provides the nameof operator to make refactoring safer and more maintainable.

What is the nameof Operator?

The nameof operator in C# returns the string representation of a variable, method, or class name at compile time. This makes your code more resilient to name changes since the compiler will catch errors if a referenced identifier is renamed or removed.

Basic Usage

Instead of using hardcoded strings, use nameof to reference identifiers dynamically:

class Person
{
    public string FirstName { get; set; }
}

void PrintPropertyName()
{
    Console.WriteLine(nameof(Person.FirstName)); // Output: "FirstName"
}

If FirstName is renamed, the compiler will flag the change, helping prevent runtime errors.

Benefits of Using nameof

  1. Safer Refactoring: When renaming identifiers, the compiler ensures nameof references update automatically.
  2. Improved Readability: Code intent is clearer, avoiding magic strings.
  3. Fewer Runtime Errors: No risk of typos or mismatches in string literals.

Practical Examples

Logging

Using nameof ensures that logs remain accurate even after refactoring:

void LogError(string message, string propertyName)
{
    Console.WriteLine($"Error in {propertyName}: {message}");
}

LogError("Invalid value", nameof(Person.FirstName));

Argument Validation

Validating method parameters without hardcoded strings:

void SetAge(int age)
{
    if (age < 0)
        throw new ArgumentException("Age cannot be negative", nameof(age));
}

Dependency Injection

When working with DI frameworks, nameof prevents issues with binding:

services.AddSingleton<ILogger, Logger>(provider =>
    new Logger(nameof(Logger)));

Conclusion

The nameof operator is a simple yet powerful feature in C# that improves code maintainability and prevents common errors during refactoring. By replacing hardcoded strings with nameof, you can make your applications more robust and future-proof.

0
35

Related

Removing duplicates from a list in C# is a common task, especially when working with large datasets. C# provides multiple ways to achieve this efficiently, leveraging built-in collections and LINQ.

Using HashSet (Fastest for Unique Elements)

A HashSet<T> automatically removes duplicates since it only stores unique values. This is one of the fastest methods:

List<int> numbers = new List<int> { 1, 2, 2, 3, 4, 4, 5 };
numbers = new HashSet<int>(numbers).ToList();
Console.WriteLine(string.Join(", ", numbers)); // Output: 1, 2, 3, 4, 5

Using LINQ Distinct (Concise and Readable)

LINQ’s Distinct() method provides an elegant way to remove duplicates:

List<int> numbers = new List<int> { 1, 2, 2, 3, 4, 4, 5 };
numbers = numbers.Distinct().ToList();
Console.WriteLine(string.Join(", ", numbers)); // Output: 1, 2, 3, 4, 5

Removing Duplicates by Custom Property (For Complex Objects)

When working with objects, DistinctBy() from .NET 6+ simplifies duplicate removal based on a property:

using System.Linq;
using System.Collections.Generic;

class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}

List<Person> people = new List<Person>
{
    new Person { Name = "Alice", Age = 30 },
    new Person { Name = "Bob", Age = 25 },
    new Person { Name = "Alice", Age = 30 }
};

people = people.DistinctBy(p => p.Name).ToList();
Console.WriteLine(string.Join(", ", people.Select(p => p.Name))); // Output: Alice, Bob

For earlier .NET versions, use GroupBy():

people = people.GroupBy(p => p.Name).Select(g => g.First()).ToList();

Performance Considerations

  • HashSet<T> is the fastest but only works for simple types.
  • Distinct() is easy to use but slower than HashSet<T> for large lists.
  • DistinctBy() (or GroupBy()) is useful for complex objects but may have performance trade-offs.

Conclusion

Choosing the best approach depends on the data type and use case. HashSet<T> is ideal for primitive types, Distinct() is simple and readable, and DistinctBy() (or GroupBy()) is effective for objects.

1
403

Closing a SqlDataReader correctly prevents memory leaks, connection issues, and unclosed resources. Here’s the best way to do it.

Use 'using' to Auto-Close

Using using statements ensures SqlDataReader and SqlConnection are closed even if an exception occurs.

Example

using (SqlConnection conn = new SqlConnection(connectionString))
{
    conn.Open();
    using (SqlCommand cmd = new SqlCommand("SELECT * FROM Users", conn))
    using (SqlDataReader reader = cmd.ExecuteReader())
    {
        while (reader.Read())
        {
            Console.WriteLine(reader["Username"]);
        }
    } // ✅ Auto-closes reader here
} // ✅ Auto-closes connection here

This approach auto-closes resources when done and it is cleaner and less error-prone than manual closing.

⚡ Alternative: Manually Close in finally Block

If you need explicit control, you can manually close it inside a finally block.

SqlDataReader? reader = null;
try
{
    using SqlConnection conn = new SqlConnection(connectionString);
    conn.Open();
    using SqlCommand cmd = new SqlCommand("SELECT * FROM Users", conn);
    reader = cmd.ExecuteReader();

    while (reader.Read())
    {
        Console.WriteLine(reader["Username"]);
    }
}
finally
{
    reader?.Close();  // ✅ Closes reader if it was opened
}

This is slightly more error prone if you forget to add a finally block. But might make sense when you need to handle the reader separately from the command or connection.

1
184

String interpolation, introduced in C# 6.0, provides a more readable and concise way to format strings compared to traditional concatenation (+) or string.Format(). Instead of manually inserting variables or placeholders, you can use the $ symbol before a string to directly embed expressions inside brackets.

string name = "Walt";
string job = 'Software Engineer';

string message = $"Hello, my name is {name} and I am a {job}";
Console.WriteLine(message);

This would produce the final output of:

Hello, my name is Walt and I am a Software Engineer

String interpolation can also be chained together into a multiline string (@) for even cleaner more concise results:

string name = "Walt";
string html = $@"
    <div>
        <h1>Welcome, {name}!</h1>
    </div>";
37
150