Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
L'operatore
Tip
Questo articolo fa parte della sezione Nozioni fondamentali per gli sviluppatori che già conoscono almeno un linguaggio di programmazione e stanno imparando C#. Se non si ha familiarità con la programmazione, iniziare prima con le esercitazioni introduttive . Per informazioni di riferimento sull'operatore completo, vedere nameof nelle informazioni di riferimento sul linguaggio.
Venire da un'altra lingua? Altri linguaggi hanno funzionalità simili. il Class.getSimpleName() di Java, Function.name e Object.keys di JavaScript, __name__ e vars() di Python e #function/#keyPath di Swift. A differenza della maggior parte di essi, nameof di C# è un costrutto che esiste esclusivamente in fase di compilazione. Non usa la riflessione, non alloca nulla in fase di esecuzione e produce una costante string incorporata nell'assembly.
L'operatore nameof restituisce l'identificatore testuale di un simbolo, ad esempio una variabile, un parametro, un tipo, un membro o uno spazio dei nomi, come costante in fase string di compilazione. Ovunque altrimenti si codificherebbe direttamente un identificatore come stringa letterale, usare nameof: il compilatore verifica che il simbolo esista e le operazioni di ridenominazione aggiornano automaticamente il risultato.
Cosa nameof restituisce
nameof restituisce l'identificatore finale nel relativo operando. Viene eseguito in fase di compilazione senza costi di runtime.
// 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
L'operando può anche essere un'espressione qualificata, che usa l'operatore dot per spostarsi da un ambito contenitore a un membro, ad esempio customer.Name, System.Consoleo List<int>.Enumerator. In tal caso, viene acquisito solo l'ultimo identificatore: nameof(customer.Name) restituisce "Name", non "customer.Name".
Convalida degli argomenti
L'uso classico consiste nel produrre il nome del parametro in un'eccezione sollevata. Passa nameof(parameter) invece della stringa letterale "parameter" in modo che una futura rinomina non renda il messaggio fuorviante:
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}!");
}
Per i controlli di valori null in particolare, preferire l'uso di helper per le eccezioni. Queste funzioni helper, come ThrowIfNull, catturano automaticamente il nome dell'argomento attraverso CallerArgumentExpressionAttribute, quindi non è necessario un nameof separato:
// 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);
// ...
}
Usare nameof per i casi in cui gli helper non coprono: ArgumentException, ArgumentOutOfRangeException (quando si convalida qualcosa di diverso da un singolo argomento) e altri messaggi di protezione.
Notifiche di modifica delle proprietà
I tipi che implementano INotifyPropertyChanged sollevano un evento il cui payload include il nome della proprietà modificata. Codificare il nome come stringa crea un bug silenzioso se la proprietà viene rinominata e la stringa non viene aggiornata. Usare nameof invece:
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));
}
Il setter chiama OnPropertyChanged(nameof(Name)) in modo che il nome della proprietà e la notifica di modifica rimangano sincronizzati. Eseguire l'esempio per visualizzare gli eventi generati:
var person = new Person();
person.PropertyChanged += (_, e) => Console.WriteLine($"changed: {e.PropertyName}");
person.Name = "Ada"; // changed: Name
person.Name = "Grace"; // changed: Name
nameof negli argomenti di attributo
nameof è valido negli argomenti dell'attributo. Il compilatore risolve gli identificatori nell'ambito circostante, inclusi i parametri del metodo di destinazione dell'attributo. Questo è il modo idiomatico per fare riferimento a un parametro a partire da un attributo come 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();
Se il parametro viene rinominato, l'argomento nameof viene aggiornato con lo stesso refactoring, quindi l'attributo non può diventare obsoleto.
Nomi qualificati
Per qualsiasi espressione qualificata, nameof restituisce solo l'ultimo identificatore:
// 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
Se ti serve il nome completamente qualificato, usa Type.FullName su un'istanza di Type.
nameof è per gli identificatori, non per i percorsi.
Preferire nameof rispetto alle stringhe identificative
Ovunque si faccia riferimento per nome nel codice a un metodo, una proprietà, un parametro, un tipo o uno spazio dei nomi, usa nameof anziché una stringa letterale. Rispetto a una stringa codificata:
- Il compilatore verifica che il simbolo esista. Un errore di ortografia diventa un errore di compilazione, non un bug di runtime invisibile all'utente.
- Il refactoring di ridenominazione aggiorna automaticamente il risultato. Le stringhe codificate in modo statico finiscono per non essere più sincronizzate.
- Il risultato è una costante in fase di compilazione, quindi non è previsto alcun costo di runtime.
Questa raccomandazione si applica alla registrazione di messaggi, argomenti di eccezione, argomenti di attributo, notifiche di modifica delle proprietà e costanti della chiave di serializzazione associate a un nome di membro.