2010-09-26 24 views
63

:base() ve :this() yapıcıların yapıcı parantezleri (hatta kodun diğer yerlerinde bile) izleyen çağrıları yapmam gereken koşullar. Bunlar ne zaman iyi uygulamaları arar ve ne zaman zorunludur?base() ve this() yapıcıların en iyi uygulamaları

+0

üzgün ... Ben bu aramalar ne yaptığını biliyoruz. Bu çağrıları yapmam gerektiğinde ya da yapmam gerektiğinde senaryo hakkında net bir görüş bildirmedim. Onları yapmazsam, ya hemen ya mahkum olurum ya da gizli bir hata ya da kötü kod kalitesi olacak yerler. Son zamanlarda böyle bir baş ağrım vardı, bu yüzden bu senaryoları açıklığa kavuşturmak istedim. - – explorer

cevap

85

: base(...)

otomatik olarak varsayılan temel kurucu arayacak.

Varsayılan kurucu yoksa, temel kurucuyu açıkça çağırmak zorunludur.

Varsayılan bir kurucu olsa bile, varsayılan kurucudan farklı bir kurucu çağırmak isteyebilirsiniz. Bu durumda hala temel kurucudan farklı bir kurucu çağırmak için base(foo, bar) kullanmak isteyebilirsiniz.

Temel sınıf varsayılan yapıcısını çağırmak istediğinizde, base()'u atlamak için kötü bir uygulama olduğunu düşünmüyorum, ancak açıklamayı seviyorsanız dahil etme konusunda hiçbir zarar görmüyorum. Bu bir tat meselesi.

: this(...)

Bu söz dizimi aynı sınıfın içinde başka farklı bir imzayla bir kurucusunu çağırmak için izin verir. Bunu yapmak asla zorunlu değildir, ancak bazen yararlı olabilir.

Kullanışlı olabileceği bir örnek, kuruculardaki ortak kodun yeniden kullanılmasıdır. Örneğin C# 3.5 veya daha önce, bir kurucunun üzerinde isteğe bağlı parametreleri simüle etmek isteyebilirsiniz: C# 4.0 isteğe bağlı parametreleri ile

Foo(int x, int y) 
{ 
    this.x = x; 
    this.y = y; 
} 

Foo(int x) : this(x, 10) {} // y defaults to 10 

artık kullanılabilir Bu yaklaşımın gerekliliğini azaltır.

Kuruculardaki kodu yeniden kullanmanın alternatif bir yolu, onu kullanmak isteyen her kurucudan çağrılan statik bir işleve dahil etmektir.

5

"C# içinde kurucu zincirleme" konusuna bakın. Bu kurucular kod tekrarını ortadan kaldırmak için yardımcı olur

MyClass():base() //default constructor calling superclass constructor 
{ 
} 

MyClass(int arg):this() //non-basic constructor calling base constructor 
{ 
    //extra initialization 
} 

- Temel ve belirli bölümlerine bölün: Temel olarak, bu gibi görünüyor. Bir temel kurucu çağrıyı atlarsanız

+0

Teşekkürler. "Yapıcı zincirleme", hatırlamadığım dönemdi. – JNappi

4

Temel sınıfı kurucusunun, kurucunuzun ilk talimatı olarak otomatik olarak çağrılmasını istediğinizde, base() yöntemini kullanırsınız. : Bu() benzer, ama aynı sınıfta başka bir kurucu çağırıyor.

Temel :() ve this(): parametreler sabit değerleri veya yapıcınızın parametrelerini temel alan ifade olarak iletebilirsiniz.

Temel sınıf varsayılan bir kurucu olmadığında (herhangi bir parametre almayan) temel yapıcıyı çağırmak zorunludur. Hangi durumda olduğunu bilmiyorum: Bu() zorunludur.

public class ABaseClass 
{ 
    public ABaseClass(string s) {} 
} 

public class Foo : AChildClass 
{ 
    public AChildClass(string s) : base(s) {} //base mandatory 
    public AChildClass() : base("default value") {} //base mandatory 
    public AChildClass(string s,int i) : base(s+i) {} //base mandatory 
} 

public class AnotherBaseClass 
{ 
    public ABaseClass(string s) {} 
    public ABaseClass():this("default value") {} //call constructor above 
} 

public class Foo : AnotherChildClass 
{ 
    public AnotherChildClass(string s) : base(s) {} //base optional 

} 
28

Öncelikle zorunlu olduklarında.

bir sınıf Derived bir sınıf Base türetilmiştir

ve BaseDerived parametreleri ile açıkça base() çağırmalıdır, varsayılan (parametresiz) yapıcısı yoktur.

public class Base { 
    public Base(int i) { } 
} 


public class Derived : Base { 
    // public Derived() { } wouldn't work - what should be given for i? 
    public Derived() : base(7) { } 
    public Derived(int i) : base(i) { } 
} 

zaman iyi bir uygulamadır? Ne zaman farklı bir kurucu aramak istersen.

Önceden verdiğim örnekte, Türetilmiş yapıdaki yapıcılara içerik eklediğinizi varsayalım.

public class Derived : Base { 
    // public Derived() { } wouldn't work - what should be given for i? 
    public Derived() : base(7) { 
     Console.WriteLine("The value is " + 7); 
    } 
    public Derived(int i) : base(i) { 
     Console.WriteLine("The value is " + i); 
    } 
} 

Burada çoğaltmayı görüyor musunuz? Bu() yapıcısını çağırmak daha basittir.

public class Derived : Base { 
    // public Derived() { } wouldn't work - what should be given for i? 
    public Derived() : this(7) { } 
    public Derived(int i) : base(i) { 
     Console.WriteLine("The value is " + i); 
    } 
} 
+0

Yani son örnekte çağrı sırası şöyle olurdu: baz (7) 've sonra Türetilmiş (7), sonra da Türetilmiş(). Başka bir deyişle, bu (7) parçanın kendisi bir 'base() '(böyle bir temel yöntem olduğu varsayılarak) tetiklemeyecektir. Doğru mu? – RayLuo

+1

Doğru; Kurucular her zaman zincirlenmişlerdir ve her sınıf kendi sınıfının yapıcılarını çağırır. Bunu kullanarak, bu sınıfın diğer kurucusunu (kendi deyimiyle ya da hiç bir argümanla ya da açıkça) 'taban' kullanacaksınız; 'base' kullanarak hangi temel sınıf kurucusunun arandığını seçersiniz. – configurator

21

Kullanım base orada miras olduğunu ve bir üst sınıf zaten ulaşmaya çalıştığınız işlevsellik sağlar zaman.

Geçerli öğeye (veya kendinize) başvurmak istediğinizde, başka bir kurucuda önceden tanımlanmış işlevselliği çoğaltmak istemediğinizde, kurucunun üstbilgisinde/imzasında kullanın (this). Temelde

, tabanını kullanarak ve bu şantiye başlığında daha sürdürülebilir ve

İşte kesinlikle anlamsız örnek daha az ayrıntılı hale kodunuzu DRY tutmaktır, ama gösteren fikrini göstermektedir düşünüyorum ikisi kullanılabilir.

class Person 
{ 
    public Person(string name) 
    { 
     Debug.WriteLine("My name is " + name); 
    } 
} 

class Employee : Person 
{ 
    public Employee(string name, string job) 
     : base(name) 
    { 
     Debug.WriteLine("I " + job + " for money."); 
    } 

    public Employee() : this("Jeff", "write code") 
    { 
     Debug.WriteLine("I like cake."); 
    } 
} 

Kullanımı:

belirsizliğe
var foo = new Person("ANaimi"); 
// output: 
// My name is ANaimi 

var bar = new Employee("ANaimi", "cook food"); 
// output: 
// My name is ANaimi 
// I cook food for money. 

var baz = new Employee(); 
// output: 
// My name is Jeff 
// I write code for money. 
// I like cake. 
İlgili konular