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);
}
}
}