Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Operátor
Tip
Tento článek je součástí části Základy pro vývojáře, kteří už znají aspoň jeden programovací jazyk a učí se jazyk C#. Pokud s programováním teprve začínáte, začněte nejprve kurzy Začínáme . Úplnou referenci operátorů najdete v referenci jazyka nameof.
Pochází z jiného jazyka? Jiné jazyky mají podobné funkce. reflexivní Class.getSimpleName() v Javě, Function.name a Object.keys v JavaScriptu, __name__ a vars() v Pythonu a #function/#keyPath ve Swiftu. Na rozdíl od většiny z nich je nameof v jazyce C# čistě konstruktem existujícím pouze v době kompilace. Nepoužívá žádnou reflexi, za běhu nic nealokuje a vytváří konstantu string, která je vložena přímo do sestavení.
Operátor nameof vrátí textový identifikátor symbolu, například proměnnou, parametr, typ, člen nebo obor názvů, jako konstantu kompilačního času string . Všude, kde byste jinak napevno zapisovali identifikátor v podobě řetězce, použijte nameof: kompilátor ověří, že symbol existuje, a přejmenování v rámci refaktoringu výsledek automaticky aktualizuje.
Co vrací nameof
nameof se vyhodnotí jako konečný identifikátor v jeho operandu. Spouští se v době kompilace a nemá žádné náklady za běhu.
// 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
Operandem může být také kvalifikovaný výraz, který používá operátor tečky k přechodu z nadřazeného oboru na člena, například customer.Name, System.Console nebo List<int>.Enumerator. V takovém případě je zaznamenán pouze poslední identifikátor: nameof(customer.Name) vrátí "Name", nikoli "customer.Name".
Ověření argumentu
Klasické použití vytváří název parametru v vyvolané výjimce. Předejte nameof(parameter) místo doslovného řetězce "parameter", aby při budoucím přejmenování nezůstala zpráva zastaralá:
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}!");
}
Pro kontrolu hodnoty null zejména upřednostněte pomocné metody pro výjimky. Tyto pomocné metody, například ThrowIfNull, automaticky zachycují název argumentu prostřednictvím CallerArgumentExpressionAttribute, takže není potřeba samostatný nameof:
// 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);
// ...
}
Použijte nameof v případech, které pomocné metody nepokrývají: ArgumentException, ArgumentOutOfRangeException (při ověřování něčeho jiného než jednoho argumentu) a další zprávy ochranných kontrol.
Oznámení o změnách vlastností
Typy, které implementují INotifyPropertyChanged, vyvolají událost, jejíž datová část obsahuje název změněné vlastnosti. Pevné zakódování názvu jako řetězec vytvoří tichou chybu, pokud je vlastnost přejmenována a řetězec není. Místo toho použijte nameof :
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));
}
Setter volá OnPropertyChanged(nameof(Name)), aby název vlastnosti a oznámení o změně zůstaly synchronizované. Spusťte příklad a uvidíte, jak se události vyvolají:
var person = new Person();
person.PropertyChanged += (_, e) => Console.WriteLine($"changed: {e.PropertyName}");
person.Name = "Ada"; // changed: Name
person.Name = "Grace"; // changed: Name
nameof v argumentech atributů
nameof je platný uvnitř argumentů atributu. Kompilátor vyhodnocuje identifikátory v okolním rozsahu platnosti, včetně parametrů metody, na kterou atribut cílí. Jedná se o idiomaticický způsob, jak odkazovat na parametr z atributu, například 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();
Pokud se parametr přejmenuje, argument nameof se v rámci stejného refaktoringu aktualizuje – atribut tak nemůže zastarat.
Kvalifikované názvy
U libovolného kvalifikovaného výrazu nameof vrátí pouze poslední identifikátor:
// 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
Pokud potřebujete plně kvalifikovaný název, použijte Type.FullName u instance Type.
nameof je určen pro identifikátory, nikoli cesty.
Upřednostňujte nameof před řetězci identifikátorů
Kdykoli v kódu odkazujete názvem na metodu, vlastnost, parametr, typ nebo obor názvů, použijte nameof místo řetězcového literálu. Ve srovnání s pevně zakódovaným řetězcem:
- Kompilátor ověří, že symbol existuje. Překlep se stane chybou sestavení, nikoli tichou chybou modulu runtime.
- Refaktoringy přejmenování aktualizují výsledek automaticky. Pevně zakódované řetězce se nesynchronizují.
- Výsledkem je konstanta doby kompilace, takže za běhu nejsou žádné náklady.
Toto doporučení platí pro protokolování zpráv, argumentů výjimek, argumentů atributů, oznámení o změnách vlastností a konstanty serializačního klíče svázané s názvem člena.