Menu

How to Use the Null Coalescing Assignment Operator in C#

The null coalescing assignment operator (??=) introduced in C# 8.0 provides a cleaner way to assign a value to a variable only when it's null. Let's see how and when to use it effectively.

Quick Example

// Instead of writing this:
if (myVariable == null)
    myVariable = defaultValue;

// You can write this:
myVariable ??= defaultValue;

Real-World Examples

Simple Property Initialization

public class UserSettings
{
    private List<string> _preferences;
    
    public List<string> Preferences
    {
        get
        {
            _preferences ??= new List<string>();
            return _preferences;
        }
    }
}

Service Caching

public class ServiceCache
{
    private ApiClient _client;
    
    public ApiClient GetClient()
    {
        _client ??= new ApiClient("https://api.example.com");
        return _client;
    }
}

Lazy Configuration Loading

public class ConfigurationManager
{
    private Dictionary<string, string> _settings;
    
    public string GetSetting(string key)
    {
        _settings ??= LoadSettingsFromFile();
        return _settings.TryGetValue(key, out var value) ? value : null;
    }
    
    private Dictionary<string, string> LoadSettingsFromFile()
    {
        // Load settings logic here
        return new Dictionary<string, string>();
    }
}

Common Gotchas

Reference vs Value Types

The operator works differently with value types - they need to be nullable:

// This won't compile
int count ??= 1;

// This works
int? count ??= 1;

Chaining Operations

// You can chain the operator
string result = first ??= second ??= "default";

// Equivalent to:
if (first == null)
{
    if (second == null)
    {
        second = "default";
    }
    first = second;
}
result = first;

Thread Safety

The operator is not thread-safe by default:

// Not thread-safe
public class SharedCache
{
    private static Dictionary<string, object> _cache;
    
    public object GetItem(string key)
    {
        // Multiple threads could evaluate null simultaneously
        _cache ??= new Dictionary<string, object>();
        return _cache.GetValueOrDefault(key);
    }
}

// Thread-safe version
public class SharedCache
{
    private static Dictionary<string, object> _cache;
    private static readonly object _lock = new object();
    
    public object GetItem(string key)
    {
        lock (_lock)
        {
            _cache ??= new Dictionary<string, object>();
            return _cache.GetValueOrDefault(key);
        }
    }
}

Performance Considerations

The null coalescing assignment operator is compiled to efficient IL code. It generally performs the same as an explicit null check:

// These compile to similar IL
obj ??= new object();

if (obj == null)
    obj = new object();

When to Use It

✅ Good use cases:

  • Lazy initialization of properties
  • Caching values
  • Setting default values for nullable types
  • Simplifying null checks in property getters

❌ Avoid using when:

  • You need thread-safe initialization (use Lazy<T> instead)
  • The right-hand expression has side effects
  • You need more complex null-checking logic

Visual Studio Tips

You can use Quick Actions (Ctrl+.) to convert between traditional null checks and the ??= operator. Look for the suggestion "Use null coalescing assignment" when you have a pattern like:

if (variable == null)
    variable = value;

Version Compatibility

This feature requires:

  • C# 8.0 or later
  • .NET Core 3.0+ or .NET Standard 2.1+
  • Visual Studio 2019+
2
61

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
393

When working with SQL Server, you may often need to count the number of unique values in a specific column. This is useful for analyzing data, detecting duplicates, and understanding dataset distributions.

Using COUNT(DISTINCT column_name)

To count the number of unique values in a column, SQL Server provides the COUNT(DISTINCT column_name) function. Here’s a simple example:

SELECT COUNT(DISTINCT column_name) AS distinct_count
FROM table_name;

This query will return the number of unique values in column_name.

Counting Distinct Values Across Multiple Columns

If you need to count distinct combinations of multiple columns, you can use a subquery:

SELECT COUNT(*) AS distinct_count
FROM (SELECT DISTINCT column1, column2 FROM table_name) AS subquery;

This approach ensures that only unique pairs of column1 and column2 are counted.

Why Use COUNT DISTINCT?

  • Helps in identifying unique entries in a dataset.
  • Useful for reporting and analytics.
  • Efficient way to check for duplicates.

By leveraging COUNT(DISTINCT column_name), you can efficiently analyze your database and extract meaningful insights. Happy querying!

1
120

Reading a file line by line is useful when handling large files without loading everything into memory at once.

✅ Best Practice: Use File.ReadLines() which is more memory efficient.

Example

foreach (string line in File.ReadLines("file.txt"))
{
    Console.WriteLine(line);
}

Why use ReadLines()?

Reads one line at a time, reducing overall memory usage. Ideal for large files (e.g., logs, CSVs).

Alternative: Use StreamReader (More Control)

For scenarios where you need custom processing while reading the contents of the file:

using (StreamReader reader = new StreamReader("file.txt"))
{
    string? line;
    while ((line = reader.ReadLine()) != null)
    {
        Console.WriteLine(line);
    }
}

Why use StreamReader?

Lets you handle exceptions, encoding, and buffering. Supports custom processing (e.g., search for a keyword while reading).

When to Use ReadAllLines()? If you need all lines at once, use:

string[] lines = File.ReadAllLines("file.txt");

Caution: Loads the entire file into memory—avoid for large files!

4
304