nameof + CallerArgumentExpression

C# 10.0 .NET 6.0

Published Updated Author Jeffrey T. Fritz Reading time

nameof and CallerArgumentExpression help your APIs report exactly what went wrong, with refactor-safe names and call-site expressions.

C# has long offered nameof for refactor-safe symbol names. C# 10 added CallerArgumentExpression so helper methods can also capture the exact argument expression used at the call site.

Why it matters

Validation and guard methods are easier to trust when failure messages are specific. This combo keeps diagnostics expressive while staying friendly to refactoring.

Practical usage

Use this pattern in shared Guard utilities, argument validators, and assertion helpers. You write the helper once, and every call site benefits from richer exception details.

Cautions

CallerArgumentExpression captures source text, not evaluated values. Keep error messages focused and avoid logging sensitive expressions directly in production paths.

Capture failed conditions in guard helpers

Pair CallerArgumentExpression with nameof to produce precise diagnostics without hard-coded parameter strings.

Valid since C# 10.0

using System;
using System.Runtime.CompilerServices;

public static class Guard
{
    public static void That(
        bool condition,
        string message,
        [CallerArgumentExpression("condition")] string? conditionExpression = null)
    {
        if (!condition)
        {
            throw new ArgumentException(
                $"{message} (Condition: {conditionExpression})",
                nameof(condition));
        }
    }
}

public static class Program
{
    public static void Main()
    {
        var quantity = -2;

        try
        {
            Guard.That(quantity > 0, "Quantity must be positive");
        }
        catch (ArgumentException ex)
        {
            Console.WriteLine(ex.Message);
            Console.WriteLine($"Param: {ex.ParamName}");
        }
    }
}

Build null-check helpers with rich error messages

Capture the original call-site expression so thrown exceptions tell you exactly what argument failed validation.

Valid since C# 10.0

using System;
using System.Runtime.CompilerServices;

public static class Ensure
{
    public static T NotNull<T>(
        T? value,
        [CallerArgumentExpression("value")] string? expression = null,
        [CallerMemberName] string? caller = null)
        where T : class
    {
        if (value is null)
        {
            throw new ArgumentNullException(
                nameof(value),
                $"'{expression}' was null when called from {caller}.");
        }

        return value;
    }
}

public static class Program
{
    public static void Main()
    {
        string? userName = null;

        try
        {
            _ = Ensure.NotNull(userName);
        }
        catch (ArgumentNullException ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

Learn more

CallerArgumentExpression attribute (Microsoft Learn)