İsteğe bağlı bir parametrenin metot bildiriminde bir varsayılan değeri vardır, bu yüzden çağıranlar onu yazmayabilir. Adlandırılmış bir argüman bir değeri konum yerine parametre adıyla geçirir. Birlikte, tek bir metodun bir yığın overload olmadan birçok çağrı şekline hizmet etmesini sağlarlar.
Çıktı:
to ana@mail.com: (no subject), retries 3
to ben@mail.com: Invoice #1042, retries 3
to cy@mail.com: (no subject) [URGENT], retries 3
to dev@mail.com: Build failed, retries 0
Üçüncü çağrı subject'i atlar ve urgent'ı adıyla ayarlar; adlandırılmış argümanlar olmadan yalnızca üçüncü konuma ulaşmak için "(no subject)"'i tekrar geçirmesi gerekirdi. Son çağrı her argümanı bildirimden farklı bir sırayla adıyla geçirir; bu geçerlidir.
Varsayılan Değerlerin Kuralları
Varsayılan bir değer derleyicinin hesaplayabileceği bir şey olmalıdır:
- bir sabit (
3,"INFO",true,1.5m, birconstalan, bir enum üyesi) - bir referans ya da nullable tip için
null default(T)ya da bir değer tipiTiçinnew T()
Çalışma zamanında değerlendirilen her şey reddedilir. Klasik örnek bir tarihtir:
static void Schedule(string task, DateTime at = DateTime.Now) { }
// error CS1736: Default parameter value for 'at' must be a compile-time constant
Standart çözüm, varsayılanı null olan ve gövdede çözülen nullable bir parametredir:
Çıktı:
backup at 2026-01-01 09:00, tags: 0
report at 2026-03-15 18:30, tags: 0
deploy at 2026-01-01 09:00, tags: 2
Aynı hile koleksiyonları da kapsar: new List<string>() varsayılanı bir sabit değildir, bu yüzden varsayılanı null yapın ve listeyi içeride oluşturun. Bu, C#'ın yalnızca sabitlere izin vererek dışladığı Python tarzı paylaşılan değiştirilebilir varsayılan hatasından da kaçınır.
Sıra Kuralları
Önce zorunlu parametreler, sonra isteğe bağlı olanlar ve (varsa) en sonda bir params dizisi gelir:
static void Log(string message, string level = "INFO", params string[] tags) { } // OK
static void Log(string level = "INFO", string message) { }
// error CS1737: Optional parameters must appear after all required parameters
ref ve out parametreleri isteğe bağlı olamaz.
Çağıran tarafta konumsal argümanlar parametreleri baştan doldurur. Adlandırılmış argümanlar onları herhangi bir sırayla izleyebilir. C# 7.2'den beri adlandırılmış bir argüman konumsal bir argümandan önce de gelebilir, ama yalnızca kendi konumundaysa (SendEmail("a@b.c", subject: "Hi", true)); eski sürümlerde adlandırılmış argümanların hepsi en sonda olmalıdır. Diğerlerini adlandırırken bile zorunlu bir parametreyi atlamak derleme hatasıdır.
Okunabilirlik İçin Adlandırılmış Argümanlar
Adlandırılmış argümanlar hiçbir şey isteğe bağlı olmadığında bile işe yarar. Literal true, false, null ve çıplak sayılar çağrı yerinde hiçbir şey söylemez:
ResizeImage(photo, 800, 600, true, false); // which is which?
ResizeImage(photo, width: 800, height: 600, keepAspect: true, upscale: false);
Bir parametreyi yeniden adlandırmak, adı kullanan çağıranlar için kırıcı bir değişiklik olur; bu, public bir kütüphanede akılda tutulmaya değer.
İsteğe Bağlı Parametreler ile Overload'lar
C# 4'ten önce aynı esneklik her kombinasyon için bir overload gerektiriyordu. İsteğe bağlı parametreler onları tek bir metotta toplar:
// overloads
static void Connect(string host) => Connect(host, 443);
static void Connect(string host, int port) => Connect(host, port, 30);
static void Connect(string host, int port, int timeoutSeconds) { /* ... */ }
// one method with optional parameters
static void Connect(string host, int port = 443, int timeoutSeconds = 30) { /* ... */ }
İkisi birden olduğunda overload çözümlemesi, hiçbir varsayılanın doldurulması gerekmeyen adayı tercih eder:
Çıktı:
Greet()
Greet(string) with Lena
Greet() iki metotla da eşleşir ve derleyici atlanmış isteğe bağlı parametresi olmayanı seçer. İki tekniği aynı adda karıştırmak çoğunlukla hedefi tahmin etmesi zor çağrılar üretir, bu yüzden her metot için birini seçin.
Varyantlar farklı kod ya da farklı parametre tipleri gerektirdiğinde overload'ları, yalnızca varsayılan değerlerde farklılaştıklarında isteğe bağlı parametreleri seçin.
Varsayılanlar Çağırana Gömülür
Varsayılan bir değer çalışma zamanında aranmaz. Derleyici, çağıran kod derlenirken onu her çağrı yerine kopyalar. Connect("api.shop.com"), Connect("api.shop.com", 443, 30)'a derlenir.
Bunun kütüphaneler için bir sonucu vardır. Bir paketin 1. sürümünün Connect(string host, int timeoutSeconds = 30) ile çıktığını ve 2. sürümün varsayılanı 10'a değiştirdiğini varsayalım. 1. sürüme karşı derlenmiş bir uygulama, 2. sürümün DLL'ini koyduktan sonra da uygulamanın kendisi yeniden derlenene kadar 30 geçirmeye devam eder. Mevcut public bir metoda yeni isteğe bağlı bir parametre eklemek de zaten derlenmiş çağıranları bozar, çünkü metodun imzası değişmiştir ve onlar hâlâ eskisini arar (çalışma zamanında bir MissingMethodException).
Bir bütün olarak derlenen tek bir uygulamanın içinde bu hiç önemli değildir. NuGet paketlerindeki public API'ler için overload'lar (varsayılanları kütüphanenin içinde tutar) ya da gövdede çözülen bir null varsayılanı sorundan kaçınır.
Varsayılanlar ve Bildirilen Tip
Aynı derleme zamanı kuralı şu anlama gelir: bir interface ve bir sınıf ikisi de varsayılan bildirdiğinde, varsayılan nesneden değil, üzerinden çağırdığınız değişkenin tipinden gelir:
Çıktı:
printing "report" x5
printing "report" x1
Aynı nesne, iki farklı varsayılan. Varsayılan değerleri bir interface ile uygulamaları arasında aynı tutun ya da onları yalnızca tek bir yerde bildirin.
Çağıran Bilgisi Öznitelikleri
İsteğe bağlı parametreler System.Runtime.CompilerServices içindeki çağıran bilgisi özniteliklerine de güç verir. Derleyici onları çağrı yerinin ayrıntılarıyla doldurur:
Çıktı:
[Main:18] starting
[SaveOrder:13] order saved
Log kütüphaneleri bir mesajın nereden geldiğini çağıran yazmadan böyle kaydeder ve INotifyPropertyChanged uygulamaları property adını böyle alır. [CallerFilePath] kaynak dosya yolunu aynı şekilde ekler.
Sıkça Sorulan Sorular
C#'ta bir parametre nasıl isteğe bağlı yapılır?
Bildirimde ona bir varsayılan değer verin: static void Log(string message, string level = "INFO"). Çağıranlar bundan sonra Log("started") ya da Log("failed", "ERROR") yazabilir. İsteğe bağlı parametreler tüm zorunlu parametrelerden sonra gelmelidir ve varsayılan bir derleme zamanı sabiti olmalıdır.
C#'ta adlandırılmış argümanlar nedir?
Parametre adıyla geçirilen argümanlardır: SendEmail(to: "ana@mail.com", urgent: true). Ortadaki isteğe bağlı parametreleri atlamanızı, argümanları herhangi bir sırayla geçirmenizi ve literal true/false ya da sayılar içeren çağrıları bir bakışta okunur kılmanızı sağlarlar.
Varsayılan parametre değeri olarak neden DateTime.Now kullanamıyorum?
Varsayılanlar derleme zamanı sabitleri olmalıdır ve DateTime.Now çalışma zamanında hesaplanır, bu yüzden derleyici CS1736, Default parameter value for 'at' must be a compile-time constant bildirir. Bunun yerine nullable bir parametre kullanın: DateTime? at = null, sonra gövdede DateTime time = at ?? DateTime.Now;.
C#'ta isteğe bağlı parametreler mi kullanmalıyım, metot overload'ları mı?
Varyantlar yalnızca varsayılan değerlerde farklılaşıyorsa isteğe bağlı parametreler daha basittir. Varyantlar farklı mantık ya da tipler gerektirdiğinde ve public kütüphanelerde overload'lar daha iyidir, çünkü varsayılan bir değer her çağırana derlenir ve onu sonradan değiştirmek zaten derlenmiş koda ulaşmaz.
"Optional parameters must appear after all required parameters" ne demek?
CS1737 hatası: varsayılan değeri olan bir parametreyi varsayılanı olmayan bir parametre izliyor. Zorunlu parametreleri başa taşıyın: (bool urgent = false, string to) değil (string to, bool urgent = false). İsteğe bağlı bir parametreden sonra yalnızca başka isteğe bağlı parametreler ya da bir params dizisi gelebilir.