Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Si Operator
Tip
Artikel ini adalah bagian dari bagian Dasar-Dasar untuk pengembang yang sudah mengetahui setidaknya satu bahasa pemrograman dan mempelajari C#. Jika Anda baru menggunakan pemrograman, mulailah dengan tutorial Memulai terlebih dahulu. Untuk referensi operator lengkap, lihat nameof di referensi bahasa.
Berasal dari bahasa lain? Bahasa lain memiliki fitur serupa.
Class.getSimpleName() reflektif milik Java, Function.name dan Object.keys milik JavaScript, __name__ dan vars() milik Python, serta #function/#keyPath milik Swift. Tidak seperti sebagian besar di antaranya, nameof milik C# merupakan konstruksi murni pada waktu kompilasi. Ini tidak menggunakan refleksi, tidak mengalokasikan apa pun saat runtime, dan menghasilkan konstanta string yang tertanam dalam assembly.
Operator nameof mengembalikan pengidentifikasi tekstual dari sebuah simbol, seperti variabel, parameter, tipe, anggota, atau namespace, sebagai konstanta string pada waktu kompilasi. Setiap kali Anda biasanya menuliskan identifier secara hardcode dalam bentuk string, gunakan nameof: kompiler memverifikasi bahwa simbol tersebut memang ada, dan refaktorisasi penggantian nama akan memperbarui hasilnya secara otomatis.
Apa yang dikembalikan nameof
nameof menghasilkan identifier final dalam operannya. Ini beroperasi saat kompilasi dan tidak menimbulkan overhead saat dijalankan.
// 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
Operand juga dapat berupa ekspresi berkualifikasi, yaitu ekspresi yang menggunakan operator titik untuk menavigasi dari cakupan induk ke sebuah anggota, seperti customer.Name, System.Console, atau List<int>.Enumerator. Dalam hal ini, hanya pengidentifikasi terakhir yang ditangkap: nameof(customer.Name) mengembalikan "Name", bukan "customer.Name".
Validasi argumen
Penggunaan yang umum adalah mencantumkan nama parameter dalam pengecualian yang dilemparkan. Teruskan nameof(parameter) alih-alih string literal "parameter" agar penggantian nama di masa mendatang tidak membuat pesan ini menjadi tidak akurat:
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}!");
}
Untuk pemeriksaan null secara khusus, lebih suka menggunakan pembantu pengecualian. Fungsi pembantu ini, seperti ThrowIfNull, menangkap nama argumen secara otomatis melalui CallerArgumentExpressionAttribute, sehingga nameof terpisah tidak diperlukan:
// 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);
// ...
}
Gunakan nameof untuk kasus yang tidak dicakup pembantu: ArgumentException, ArgumentOutOfRangeException (saat memvalidasi sesuatu selain satu argumen), dan pesan penjaga lainnya.
Pemberitahuan perubahan properti
Tipe yang mengimplementasikan INotifyPropertyChanged memicu event dengan payload yang menyertakan nama properti yang diubah. Menetapkan nama tersebut secara hardcode sebagai string dapat menimbulkan bug yang tidak langsung terlihat jika nama properti diubah tetapi string tersebut tidak ikut diubah. Gunakan nameof sebagai gantinya:
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 memanggil OnPropertyChanged(nameof(Name)) sehingga nama properti dan notifikasi perubahan selalu sinkron. Jalankan contoh untuk melihat event terpicu:
var person = new Person();
person.PropertyChanged += (_, e) => Console.WriteLine($"changed: {e.PropertyName}");
person.Name = "Ada"; // changed: Name
person.Name = "Grace"; // changed: Name
nameof dalam argumen atribut
nameof valid di dalam argumen atribut. Kompilator menentukan referensi identifier dalam cakupan yang melingkupinya, termasuk parameter dari metode yang dituju oleh atribut tersebut. Ini adalah cara idiomatik untuk merujuk ke parameter dari atribut seperti 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();
Jika parameter itu diubah namanya, argumen nameof diperbarui melalui refaktorisasi yang sama — atributnya tidak akan menjadi usang.
Nama yang memenuhi syarat
Untuk ekspresi yang memenuhi syarat, nameof hanya mengembalikan pengidentifikasi terakhir :
// 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
Jika Anda memerlukan nama yang sepenuhnya memenuhi syarat, gunakan Type.FullName pada Type instans.
nameof adalah untuk pengidentifikasi, bukan jalur.
Lebih suka nameof daripada string pengidentifikasi
Di mana saja Anda merujuk ke metode, properti, parameter, jenis, atau namespace berdasarkan nama dalam kode, gunakan nameof alih-alih string literal. Dibandingkan dengan string yang dikodekan secara permanen:
- Pengkompilasi memverifikasi bahwa simbol ada. Kesalahan ketik menjadi kesalahan build, bukan bug runtime senyap.
- Ganti nama pemfaktoran ulang memperbarui hasil secara otomatis. String yang dikodekan secara permanen tidak sinkron.
- Hasilnya adalah konstanta waktu kompilasi, sehingga tidak ada biaya runtime.
Rekomendasi ini berlaku untuk mencatat pesan, argumen pengecualian, argumen atribut, pemberitahuan perubahan properti, dan konstanta kunci serialisasi yang terkait dengan nama anggota.