The nameof Operator · How it works

3 min read
5 min read
Rapid overview

How it works

Basics

Q: What does nameof do?

A: It turns a code symbol into its name as a string, checked by the compiler.

public void Ship(Order order, string address)
{
    if (order is null) throw new ArgumentNullException(nameof(order));     // "order"
    if (string.IsNullOrWhiteSpace(address))
        throw new ArgumentException("Address is required.", nameof(address)); // "address"
}

nameof(Order)             // "Order"
nameof(Order.Total)       // "Total"   (instance member, accessed through the type name)
nameof(order.Customer.Id) // "Id"      (only the last identifier)
nameof(System.Text.Json)  // "Json"
nameof(Ship)              // "Ship"
Q: Why use nameof instead of a string literal?

A: Refactoring safety and compile-time checking. If you rename address to shippingAddress with an IDE rename, nameof(address) is updated with it; "address" silently becomes wrong. A typo in nameof(adress) is a compile error; in "adress" it is a bug you find in production logs.

Q: What does nameof cost at runtime?

A: Nothing. The compiler replaces nameof(x) with the string literal "x" in the IL. The operand is not evaluated: nameof(customer.Address.City) does not touch customer, so it cannot throw even if customer is null.


What name you get

  • nameof(System.Collections.Generic.List<int>)"List"
  • nameof(Dictionary<string, int>.Count)"Count"
  • nameof(System.Console)"Console"
  • nameof(Outer.Inner)"Inner"
Q: What does nameof return for generics, namespaces and qualified names?

A: Always the final simple identifier, without namespace, generic arguments or containing type:

Since C# 14 you can also write an unbound generic type, nameof(List<>)"List". For a fully qualified name use typeof(List<int>).FullName, which is a runtime call and gives the CLR name ("System.Collections.Generic.List1[[System.Int32, …]]"`).

Q: Can you use nameof with a method group or overloaded method?

A: Yes: nameof(Console.WriteLine) is "WriteLine"; overloads do not matter because only the name is used. You do not add parentheses or arguments.

Q: Can nameof refer to a parameter inside an attribute on the same method?

A: Since C# 11, yes. This is common with nullable-analysis attributes:

[return: NotNullIfNotNull(nameof(input))]
public static string? Normalize(string? input) => input?.Trim();

Before C# 11 you had to write the string "input".


Where you use it

  • Argument validation: throw new ArgumentOutOfRangeException(nameof(quantity)).
  • Property change notification: OnPropertyChanged(nameof(Total)) for a dependent property (the property's own name is better supplied by [CallerMemberName]).
  • Logging and exception messages: _logger.LogWarning("{Method} retrying", nameof(SyncAsync)).
  • Attributes and constants: [DebuggerDisplay("{" + nameof(Name) + "}")], const string Key = nameof(Settings.Timeout);, case nameof(Status.Active):.
  • Configuration sections: configuration.GetSection(nameof(SmtpOptions)) binding a section named after the class.
  • ASP.NET Core: CreatedAtAction(nameof(GetById), new { id }, dto).
  • EF Core where strings are required: modelBuilder.Entity<Order>().Property<DateTime>(nameof(Order.CreatedAt)), or string-based Include.
Q: Give common real-world uses of nameof.

A:


Traps

Q: Why does RedirectToAction("Index", nameof(OrdersController)) fail?

A: nameof(OrdersController) is "OrdersController", but MVC routing expects the controller name without the Controller suffix ("Orders"). Either write "Orders" or strip the suffix with a helper.

Q: Does nameof return the JSON or database name of a property?

A: No. It returns the C# identifier. If the property has [JsonPropertyName("total_amount")] or an EF Core HasColumnName("amount"), nameof still gives "Total". Anything that must match the serialized or column name has to read that metadata instead.

Q: What is the difference between nameof, typeof(T).Name and [CallerMemberName]?

A: nameof(T) is a compile-time constant of the name as written in source. typeof(T).Name is a runtime call that returns the CLR name, which for generics includes the arity: typeof(List<int>).Name is `"List1"`. [CallerMemberName]` gives the name of the calling member, filled in at each call site, so a helper does not need to be told who called it.

Q: Is nameof a reserved keyword?

A: No, it is a contextual keyword. If a method or variable called nameof is in scope, nameof(x) binds to it instead, which keeps old code compiling. You will almost never hit this, but it explains why tools treat it as an identifier in some edge cases.