Caller info attributes C# 5.0 have been useful for capturing the calling member name, file path and line number.
C# 10.0 provides a CallerArgumentExpression attribute that can be applied to a method parameter in order to capture the source code passed to another parameter.
Code
csharp
ArgumentNullException.ThrowIfNull(customerId);
var customer = Find(c => c.Id == customerId);
// ...
Customer Find(Func<Customer, bool> predicate, [CallerArgumentExpression("predicate")] string code = "")
{
return db.Customers.FirstOrDefault(predicate)
?? throw new EntityNotFoundException("Could not find Customer matching " + code);
}csharp
if (customerId == null) throw new ArgumentNullException(nameof(customerId));
var customer = Find(c => c.Id == customerId, "c => c.Id == customerId");
// ...
Customer Find(Func<Customer, bool> predicate, string code = "")
{
return db.Customers.FirstOrDefault(predicate)
?? throw new EntityNotFoundException("Could not find Customer matching " + code);
}Notes
- The parameter receiving the expression must be optional; the compiler fills it in only when the caller omits it
ArgumentNullException.ThrowIfNull, added in .NET 6, uses this attribute to report the argument's name- Reduces the need to repeat nameof C# 6.0 in guard clauses