nameof işleci

Tip

Bu makale, en az bir programlama dili bilen ve C# dilini öğrenen geliştiriciler için Temel Bilgiler bölümünün bir parçasıdır. Programlamaya yeni başladıysanız ilk olarak Başlangıç öğreticileri ile başlayın. İşleçlerle ilgili tam başvuru için dil referansındaki nameof bölümüne bakın.

Başka bir dilden mi geliyorsunuz? Diğer diller benzer özelliklere sahiptir. Java'nın yansıtma özelliği Class.getSimpleName(), JavaScript'in Function.name ve Object.keys, Python'ın __name__ ve vars() ve Swift'in #function/#keyPath. Bunların çoğundan farklı olarak, C#' nameof ler saf bir derleme zamanı yapısıdır. Yansıma kullanmaz, çalışma zamanında bellek ayırmaz ve derlemeye gömülü bir sabit string üretir.

nameof işleci bir sembolün değişken, parametre, tür, üye veya ad alanı gibi metin tanımlayıcısını derleme zamanı string sabiti olarak döndürür. Normalde bir tanımlayıcıyı dize olarak sabit kodlayacağınız her yerde nameof kullanın: derleyici simgenin var olduğunu doğrular ve yeniden adlandırma yeniden düzenlemeleri sonucu otomatik olarak günceller.

nameof öğesinin döndürdüğü değer

nameof işlenenindeki son tanımlayıcıyı değerlendirir. Derleme zamanında çalışır ve çalışma zamanında ek yük oluşturmaz.

// 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

İşlenen, içeren bir kapsamdan bir üyeye gitmek için nokta işlecini kullanan bir nitelikli ifade de olabilir; örneğin customer.Name, System.Console veya List<int>.Enumerator. Bu durumda, yalnızca son tanımlayıcı yakalanır: nameof(customer.Name) döndürür "Name", değil "customer.Name".

Argüman doğrulama

Klasik kullanım, fırlatılan bir özel durumda parametre adını belirtmektir. nameof(parameter) yerine sabit dize "parameter"’i iletin; böylece gelecekte yapılacak bir yeniden adlandırma, iletinin yanlış hâle gelmesine neden olmaz:

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}!");
}

Özel olarak null denetimler için özel durum yardımcılarını kullanmayı tercih edin. ThrowIfNull gibi bu yardımcılar, argümanın adını CallerArgumentExpressionAttribute aracılığıyla otomatik olarak alır; böylece ayrı bir nameof gerekmez:

// 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);
    // ...
}

Yardımcıların kapsamadığı durumlarda nameof kullanın: ArgumentException, ArgumentOutOfRangeException (tek bir bağımsız değişken dışındaki bir şeyi doğrularken) ve diğer guard iletileri.

Özellik değişikliği bildirimleri

Uygulayan INotifyPropertyChanged türler, yükü değiştirilen özelliğin adını içeren bir olayı tetikler. Adı dize olarak sabit kodlamak, özellik yeniden adlandırıldığında ancak dize güncellenmediğinde sessiz bir hataya yol açar. Bunun yerine şunu kullanın 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));
}

Ayarlayıcı, özellik adıyla değişiklik bildiriminin eşzamanlı kalması için OnPropertyChanged(nameof(Name)) çağırır. Olayların tetiklendiğini görmek için örneği çalıştırın:

var person = new Person();
person.PropertyChanged += (_, e) => Console.WriteLine($"changed: {e.PropertyName}");

person.Name = "Ada";    // changed: Name
person.Name = "Grace";  // changed: Name

nameof öznitelik argümanlarında

nameof , öznitelik bağımsız değişkenlerinin içinde geçerlidir. Derleyici, özniteliğin hedef aldığı yöntemin parametreleri de dahil olmak üzere çevresindeki kapsamdaki tanımlayıcıları çözümler. Bu, NotNullIfNotNullAttribute gibi bir öznitelikten bir parametreye başvurmanın yerleşik yoludur:

// 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();

Parametre yeniden adlandırılırsa, nameof bağımsız değişkeni de aynı yeniden düzenleme işlemiyle güncellenir; öznitelik güncelliğini yitiremez.

Nitelenmiş adlar

Tüm nitelenmiş ifadeler için yalnızca nameofson tanımlayıcıyı döndürür:

// 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

Tam ada ihtiyacınız varsa bir Type.FullName örnekte kullanınType. nameof tanımlayıcılar içindir, yollar için değil.

Tanımlayıcı dizeleri yerine nameof tercih edin

Kodda bir yönteme, özelliğe, parametreye, türe veya ad alanına adıyla başvurduğunuz her yerde, dize sabiti yerine nameof kullanın. Sabit kodlanmış dizeyle karşılaştırıldığında:

  • Derleyici, sembolün mevcut olduğunu doğrular. Yazım hatası, sessiz bir çalışma zamanı hatası değil, derleme hatası haline gelir.
  • Yeniden adlandırma yeniden düzenlemeleri sonucu otomatik olarak güncelleştirir. Koda gömülü metinler zamanla senkronizasyondan çıkar.
  • Sonuç bir derleme zamanı sabiti olduğundan çalışma zamanı maliyeti yoktur.

Bu öneri, bir üye adına bağlı günlük iletileri, özel durum bağımsız değişkenleri, öznitelik bağımsız değişkenleri, özellik değişikliği bildirimleri ve serileştirme anahtarı sabitleri için geçerlidir.

Ayrıca bakınız