İsteğe bağlı parametreler veya aşırı yüklenmiş yapıcılar


28

Bir uygulama yapıyorum DelegateCommandve yapıcı (lar) ı uygulamak üzereyken, aşağıdaki iki tasarım seçeneğiyle karşılaştım:

1: Birden fazla aşırı yükleniciye sahip olmak

public DelegateCommand(Action<T> execute) : this(execute, null) { }

public DelegateCommand(Action<T> execute, Func<T, bool> canExecute)
{
    this.execute = execute;
    this.canExecute = canExecute;
}

2: İsteğe bağlı parametreli yalnızca bir kurucuya sahip olmak

public DelegateCommand(Action<T> execute, Func<T, bool> canExecute = null)
{
    this.execute = execute;
    this.canExecute = canExecute;
}

Hangisini kullanacağımı bilmiyorum, çünkü önerilen iki yoldan biriyle ne gibi avantajların / dezavantajların geldiğini bilmiyorum . Her ikisi de böyle çağrılabilir:

var command = new DelegateCommand(this.myExecute);
var command2 = new DelegateCommand(this.myExecute, this.myCanExecute);

Birisi lütfen beni doğru yöne çevirip geribildirim verebilir mi?


4
ÖPÜCÜK ve YAGNI. Şüphe durumunda, her ikisini de uygulayın. Bir süre sonra, her iki kurucu için referansları arayın. İçlerinden biri asla dışarıda tüketilmezse bu beni şaşırtmazdı. Veya marjinal olarak tüketilir. Bu, kodun statik analizini yaparken bulmak kolay bir şeydir.
Laiv

1
Statik yapıcılar (gibi Bitmap.FromFile) de bir seçenek
BlueRaja - Danny Pflughoeft 27:18


2
@Laiv Bir şey mi özlüyorum? Aynı şekilde kullanılırlar ve bu nedenle aynı imzaya sahiptirler. Referansları arayamaz ve arayanın hangisini düşündüğünü söyleyemezsin. OP'nin ikinci bir tartışmaya sahip olup olmayacağına değiniyor olsanız bile, kulağa daha çok geliyor, fakat OP'nin sorduğu şey bu değil (ve bazen ikisine de ihtiyaç duyduklarından emin olabilirler.
Kat

2
@Voo Openedge | Progress 10.2B için derleyici onları yok sayar. Ayrılmayan yöntem değiştirme stratejimizi neredeyse öldürdü; bunun yerine, aynı etki için aşırı yükleme kullanmamız gerekiyordu.
Bret

Yanıtlar:


24

Birden fazla kurucuyu varsayılan değerler yerine tercih ediyorum ve şahsen iki kurucu örneğinizden hoşlanmıyorum, farklı şekilde uygulanması gerekiyor.

Birden fazla kurucu kullanmanın nedeni, ana yapının sadece tüm parametrelerin boş olup olmadığını ve geçerli olup olmadıklarını kontrol edebilmesidir, diğer yapıcılar ana yapı için varsayılan değerler sağlayabilir.

Ancak örneklerinizde aralarında fark yoktur, çünkü ikincil kurucu bile nullbir varsayılan değer olarak geçer ve birincil kurucu da varsayılan değeri bilmek zorundadır. Bence olmamalı.

Bu, bu şekilde uygulandığında daha temiz ve daha iyi ayrılacağı anlamına gelir:

public DelegateCommand(Action<T> execute) : this(execute, _ => true) { }

public DelegateCommand(Action<T> execute, Func<T, bool> canExecute)
{
    this.execute = execute ?? throw new ArgumentNullException(..);
    this.canExecute = canExecute ?? throw new ArgumentNullException(..);
}

iletinin, _ => truetüm parametreleri de denetleyen nullve varsayılanları önemsemediğini belirten birincil kurucuya iletildiğini unutmayın.


Ancak en önemli nokta, genişletilebilirliktir. Gelecekte kodunuzu uzatma olasılığınız olduğunda birden fazla yapıcı daha güvenlidir. Daha fazla gerekli parametreler eklerseniz ve isteğe bağlı olanların sona ermesi gerekiyorsa, mevcut tüm uygulamalarınızı kıracaksınız. Eski yapıcıyı oluşturabilir [Obsolete]ve kullanıcılara kodlarını ihlal etmeden yeni uygulamaya geçmeleri için zaman vererek, kaldırılacağını kullanıcılara bildirebilirsiniz.


Öte yandan, isteğe bağlı çok fazla parametre yapmak da kafa karıştırıcı olacaktır çünkü bunların bir senaryoda istenmesi ve diğerinde isteğe bağlı olması durumunda, sadece doğru kurucuya basitçe parametrelerini bakarak bakmak yerine dokümantasyonu incelemeniz gerekir.


12
Öte yandan isteğe bağlı çok fazla parametre yapmak kafa karıştırıcı olurdu ... Dürüst olmak gerekirse, çok fazla parametreye sahip olmak (isteğe bağlı olup olmadıklarına bakmaksızın) kafa karıştırıcıdır.
Andy,

1
@DavidPacker Sizinle aynı fikirdeyim, fakat kaç tane parametrenin çok fazla olduğu başka bir hikaye, sanırım ;-)
t3chb0t

2
Parametre ihmal eden bir yapıcıya sahip olmakla, parametre için varsayılan olan bir kurucuya sahip olmak arasında başka bir fark vardır. İlk durumda, arayan kişi parametrenin iletilmesini açıkça önleyebilir, ikinci durumda arayanlar yapamaz - çünkü hiçbir parametreyi geçmemek, varsayılan değeri geçmekle aynı değildir. Yapıcının bu ayrımı yapması gerekiyorsa, iki yapıcı gitmek için tek yoldur.
Gary McGill

1
Örneğin, isteğe bağlı olarak bir CultureInfonesneyle oluşturabileceğim dizeleri biçimlendiren bir sınıfım olduğunu varsayalım . Ben izin bir API tercih ediyorum CultureInfoparametre ek bir parametre yoluyla temin edilecek, ancak eğer ısrar edildi ve ardından verilen o gerektiğini değil olması null. Bu şekilde, tesadüfi nulldeğerler, "hiçbiri" olarak yanlış yorumlanmaz.
Gary McGill

Genişletilebilirliğin isteğe bağlı parametrelere karşı gerçekten bir neden olduğundan emin değilim ; Eğer hiç gerekli parametrelere sahipseniz ve bunların sayısını değiştirirseniz, Obsoleteisteğe bağlı parametreleriniz olsun veya olmasın, bir şeyleri kırmaktan kaçınmak istiyorsanız, yeni bir yapıcı ve eski bir tane oluşturmak zorunda kalacaksınız. İsteğe bağlı parametrelerle yalnızca Obsoletebirini kaldırmanız gerekir.
Herohtar

17

Yapıcıda yaptığınız tek şey basit bir ödev olduğu düşünüldüğünde, tek kurucu çözümü sizin durumunuz için daha iyi bir seçim olabilir. Diğer yapıcı ekstra işlevsellik sağlamaz ve yapıcı tasarımından, ikinci argümanın sağlanması gerekmeyen iki parametreli olduğu açıktır.

Birden fazla yapıcı, farklı türlerden bir nesne oluştururken anlamlı olur. Bu durumda, inşaatçılar harici bir fabrikaya ikame olurlar çünkü girdi parametrelerini işlerler ve onları inşa edilen sınıfın doğru bir iç özellik temsiline biçimlendirirler. Ancak bu sizin durumunuzda gerçekleşmez, bu nedenle neden tek bir kurucunun fazlasıyla yeterli olması gerekir.


3

Her yaklaşımın parlayabileceği iki farklı durum olduğunu düşünüyorum.

İlk olarak, basit kurucularımız olduğunda (ki bu genellikle benim tecrübelerime göre), parlamak için isteğe bağlı argümanları göz önünde bulundururum.

  1. Yazılması gereken kodu (ve dolayısıyla okunması gereken) en aza indirir.
  2. Dokümantasyonun bir yerde olduğundan ve tekrarlanmadığından emin olabilirsiniz (kötüdür çünkü eski hale gelebilecek fazladan bir alan açar).
  3. Çok sayıda isteğe bağlı argüman varsa, kafa karıştırıcı bir dizi oluşturucu kombinasyonundan kaçınabilirsiniz. Heck, sadece isteğe bağlı 2 argümanla (birbiriyle ilgisiz) bile, eğer ayrı, aşırı yüklenen yapıcılar istiyorsanız, 4 yapıcıya sahip olmanız gerekirdi (hiç olmayan versiyon, her bir versiyon, her ikisi de versiyon). Bu belli ki iyi ölçeklenmiyor.

Buuuut, kuruculardaki isteğe bağlı argümanların işleri daha net bir şekilde karıştırdığı durumlar var. Açık bir örnek, bu isteğe bağlı argümanların münhasır olmadığı zamandır (örneğin, birlikte kullanılamaz). Yalnızca gerçekten geçerli argüman kombinasyonlarına izin veren aşırı yüklenicilere sahip olmak, bu kısıtlamanın derlenmesinde derlenmesini sağlayacaktır. Bununla birlikte, bu vaka ile karşılaşmaktan da kaçınmanız gerekir (örneğin, her sınıfın özel davranışı yaptığı bir tabandan miras alan çoklu sınıflarla).


İsteğe bağlı birden fazla parametre ile permütasyon patlamasından bahsetmek için +1.
Jpsy
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.