Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
De operator
Tip
Dit artikel maakt deel uit van de sectie Grondbeginselen voor ontwikkelaars die al ten minste één programmeertaal kennen en C# leren. Als u nieuw bent in programmeren, begint u eerst met de Aan de slag-handleidingen. Zie nameof in de taalreferentie voor de volledige operatorreferentie.
Komt u uit een andere taal? Andere talen hebben vergelijkbare functies. Java reflecterende Class.getSimpleName(), javaScript's Function.name en Object.keys, Python __name__ en vars(), en swift's #function/#keyPath. In tegenstelling tot de meeste daarvan is C#'s nameof een pure compileertijdconstructie. Het gebruikt geen reflectie, alloceert niets tijdens runtime en genereert een constante string die in de assembly is ingebakken.
De nameof operator retourneert de tekstuele id van een symbool, zoals een variabele, parameter, type, lid of naamruimte, als een compilatietijdconstante string . Waar u anders een id als tekenreeks zou hardcoderen, gebruikt u nameof: de compiler controleert of het symbool bestaat en hernoemingsrefactoringen werken het resultaat automatisch bij.
Wat nameof teruggeeft
nameof evalueert naar de uiteindelijke id in de operand. Deze wordt uitgevoerd tijdens het compileren en heeft geen runtimekosten.
// nameof produces the textual identifier of a symbol at compile time.
Console.WriteLine(nameof(Customer)); // Customer
Console.WriteLine(nameof(Customer.Name)); // Name
var customer = new Customer("Ada");
Console.WriteLine(nameof(customer)); // customer
Console.WriteLine(nameof(customer.Name)); // Name
De operand kan ook een gekwalificeerde expressie zijn, een expressie waarbij de puntoperator wordt gebruikt om van een omvattend bereik naar een lid te navigeren, zoals customer.Name, System.Console of List<int>.Enumerator. In dat geval wordt alleen de laatste id vastgelegd: nameof(customer.Name) retourneert "Name", niet "customer.Name".
Argumentvalidatie
De klassieke toepassing is het vermelden van de parameternaam in een opgeworpen exceptie. Geef nameof(parameter) in plaats van de letterlijke tekenreeks "parameter" door, zodat een toekomstige naam het bericht niet kan laten liggen:
try
{
Greet("");
}
catch (ArgumentException ex)
{
// The exception's ParamName is the literal "name", produced by nameof at compile time.
Console.WriteLine($"{ex.ParamName}: {ex.Message}");
}
static void Greet(string name)
{
if (string.IsNullOrWhiteSpace(name))
{
throw new ArgumentException("Name must be non-empty.", nameof(name));
}
Console.WriteLine($"Hello, {name}!");
}
Voor null-controles geeft u de voorkeur aan het gebruik van uitzonderingshelpers. Deze helpers, zoals ThrowIfNull, leggen de naam van het argument automatisch vast via CallerArgumentExpressionAttribute, dus een afzonderlijke nameof is niet nodig:
// ArgumentNullException.ThrowIfNull captures the argument's name automatically
// through [CallerArgumentExpression], so a separate nameof isn't required for
// the null check. Use nameof for cases the helpers don't cover.
Customer? maybeCustomer = null;
try
{
Save(maybeCustomer);
}
catch (ArgumentNullException ex)
{
Console.WriteLine(ex.ParamName); // customer
}
static void Save(Customer? customer)
{
ArgumentNullException.ThrowIfNull(customer);
// ...
}
Gebruik nameof voor de gevallen die de helpers niet afdekken: ArgumentException, ArgumentOutOfRangeException (bij het valideren van iets anders dan één enkel argument) en andere guardberichten.
Meldingen over het wijzigen van eigenschappen
Typen die INotifyPropertyChanged implementeren, roepen een gebeurtenis op waarvan de payload de naam bevat van de eigenschap die is gewijzigd. Door de naam hard gecodeerd als tekenreeks op te nemen, ontstaat er een stille bug als de eigenschap wordt hernoemd en de tekenreeks niet. Gebruik nameof in plaats daarvan:
public sealed class Person : INotifyPropertyChanged
{
private string _name = "";
public string Name
{
get => _name;
set
{
if (_name == value) return;
_name = value;
// nameof keeps the property name and the change notification in sync.
// Renaming the property automatically updates this argument.
OnPropertyChanged(nameof(Name));
}
}
public event PropertyChangedEventHandler? PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string? propertyName = null) =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
De setter roept OnPropertyChanged(nameof(Name)) aan zodat de naam van de eigenschap en de wijzigingsmelding gesynchroniseerd blijven. Voer het voorbeeld uit om te zien dat de gebeurtenissen worden geactiveerd:
var person = new Person();
person.PropertyChanged += (_, e) => Console.WriteLine($"changed: {e.PropertyName}");
person.Name = "Ada"; // changed: Name
person.Name = "Grace"; // changed: Name
nameof in kenmerkargumenten
nameof is geldig binnen kenmerkargumenten. De compiler zoekt id's op in de omringende scope, met inbegrip van de parameters van de methode waarop het kenmerk is gericht. Dit is de idiomatische manier om te verwijzen naar een parameter van een kenmerk zoals NotNullIfNotNullAttribute:
// nameof works inside attribute arguments. The compiler resolves the
// identifier even when the attribute targets a method or its parameters.
Console.WriteLine(NormalizeOrNull(" hi ") ?? "<null>"); // hi
Console.WriteLine(NormalizeOrNull(null) ?? "<null>"); // <null>
[return: NotNullIfNotNull(nameof(input))]
static string? NormalizeOrNull(string? input) => input?.Trim();
Als de naam van de parameter is gewijzigd, wordt het nameof argument bijgewerkt met dezelfde herstructurering. Het kenmerk kan niet verouderd zijn.
Gekwalificeerde namen
Voor elke gekwalificeerde expressie retourneert nameof alleen de laatste identifier:
// For a qualified expression, nameof returns only the final identifier.
Console.WriteLine(nameof(System.Collections.Generic.List<int>)); // List
Console.WriteLine(nameof(Customer.Name)); // Name
Als u de volledig gekwalificeerde naam nodig hebt, gebruikt u Type.FullName op een Type-instantie.
nameof is voor identificatoren, niet voor paden.
Gebruik bij voorkeur nameof in plaats van id-tekenreeksen
Overal waar u verwijst naar een methode, eigenschap, parameter, type of naamruimte op naam in code, gebruikt nameof u in plaats van een letterlijke tekenreeks. Vergeleken met een vastgelegde tekenreeks:
- De compiler controleert of het symbool bestaat. Een typefout wordt een buildfout, niet een stille runtimefout.
- Refactorings voor naamwijzigingen werken het resultaat automatisch bij. In code vastgelegde tekenreeksen gaan niet meer synchroon.
- Het resultaat is een compilatieconstante, dus er zijn geen runtimekosten.
Deze aanbeveling is van toepassing op logboekregistratieberichten, uitzonderingsargumenten, kenmerkargumenten, meldingen over eigenschappenwijziging en serialisatiesleutelconstanten die zijn gekoppeld aan een lidnaam.