2009-10-30 18 views
25

Başlık biraz belirsiz olabilir, ancak bunu daha iyi anlayamadım.Temel kurucuya göndermeden önce parametre değerlerini değiştirme

Bir temel kurucuyu çağırmadan önce türetilmiş bir yapıcıyı arayaamayacağımı fark ettim, ancak bir şekilde değerleri temel almayacak şekilde değiştirebilir/oluşturabilir miyim? I temel kurucu için gerekli değeri anlaması türetilmiş bir sınıf varsa

public enum InputType 
{ 
    Number = 1, 
    String = 2, 
    Date = 3 
} 

public class BaseClass 
{ 
    public BaseClass(InputType t) 
    { 
     // Logic 
    } 
} 

public class DerivedClass : BaseClass 
{ 
    public DerivedClass(int i) 
     : base(value) 
    // Can I do something to infer what value should be here? 
    { 
     // Logic 
    } 
} 

(bu örnekte, InputType.Number bir int için geçerli olacak şekilde,), örneğin

, değiştirmek için bir yol yoktur ve/veya türetilmiş yapıcının çalıştırılmasından önce temel kurucuya iletilen değerler oluşturulsun mu?

cevap

37

Temel sınıf kurucusunun parametre listesinde statik yöntemleri arayabileceğinizi umuyorum.

public class DerivedClass : BaseClass 
{ 
    public DerivedClass(int i) 
     : base(ChooseInputType(i)) 
    { 
    } 

    private static InputType ChooseInputType(int i) 
    { 
     // Logic 
     return InputType.Number; 
    } 
} 
2

Evet. Değeri değiştirmek için örneğe erişmeyen normal ifadeleri kullanmak iyidir. Örneğin

public DerivedClass(int i) 
    : base((InputType)i) 
{ 
} 
+0

DerivedClass yapıcısında mantık yoluyla "değer" yaratamazsınız, çünkü temel (...) önce çalışır. –

+0

@Reed, bir yazım hatası oldu. Koymak için değil (InputType) i. Sabit – JaredPar

+0

Evet, yayınlayabilirsiniz. Ama mantığını değer yaratmak için kullanmanın bir yolunu soruyordu. –

0

sayılı

için temel kurucu DerivedClass kurucu herhangi bir mantığa önce çalıştırılır, böylece mantık enjekte etmek için bir yol yoktur.

Ancak, temel sınıf yapıcısını çalıştırabilir, ardından değerleri değiştirmek için derlenmiş sınıfın yapıcısı sırasında temel sınıftaki özellikleri ayarlayabilirsiniz.

0

Ne

Ama sonra bu kodu göstermek temel kurucu çağırmadan önce türetilmiş bir yapıcısı arayamayacağımı

ben fark

demek

public DerivedClass(int i) 
    : base(value) 
{ 
    // Is it possible to set "value" here? 
    // Logic 
} 

zaman bu kodu Temel sınıf yapıcısı zaten çalıştıran blok girilir. Ancak, bir ifadedeki değeri, temel kurucuya iletmeden önce (bazı bariz kısıtlamalarla) değiştirebilirsiniz. Ancak, kurucuya bir giriş olmadığı sürece 'değere' erişemezsiniz.

+0

Bkz. Düzenle, yanlış satırdaki yorumu yazdım. Bunu temel kurucu çağrısının altına yazmayın. –

+0

Tamam, diğerlerinin size, temel kurucuya göndermeden önce değeri değiştirebileceğinizi önerdiklerini görüyorum. –

3

Sen türetilmiş sınıfın statik bir yöntem oluşturmak ve orada mantığı koyabilirsiniz:

public enum InputType { 
    Number = 1, 
    String = 2, 
    Date = 3 
} 

public class BaseClass { 
    public BaseClass(InputType t) { 
     // Logic 
    } 
} 

public class DerivedClass : BaseClass { 
    public DerivedClass(int i) 
     : base(GetInputType(i)) { 
     // Is it possible to set "value" here? 
     // Logic 
    } 

    private static InputType GetInputType(Int32 parameter) { 
     // Do something with parameter 
     // and return an InputType 

     return (InputType)Enum.Parse(typeof(InputType), parameter); 
    } 
} 
5

Sen temel kurucu geçirmek için bir değer hesaplamak için statik bir yöntemi kullanabilirsiniz.

public class DerivedClass : 
    BaseClass 
{ 
    public 
    DerivedClass(int i) : 
     base(ComputedValue(i)) 
    { 
    } 

    public static InputType 
    ComputedValue(int i) 
    { 
     return InputType.Number; // or any other computation you want here 
    } 
} 
1

Bir kesmek ayrı statik yöntem lambda veya anonim temsilci kullanmaktır tanıtan olmadan base() fıkrada keyfi mantığı koymak. base()'un içindeki ifade tüm yapıcı parametrelerinin kapsamındadır, böylece bunları lambda içinde serbestçe kullanabilirsiniz. Örneğin. (diyelim C# 2 diyelim.0 yüzden) aynı şey için tek astar yazmak için hiçbir LINQ var:

class Base 
{ 
    public Base(int[] xs) {} 
} 

class Derived : Base 
{ 
    public Derived(int first, int last) 
     : base(
      ((Func<int[]>)delegate 
      { 
       List<int> xs = new List<int>(); 
       for (int x = first; x < last; ++x) 
       { 
        xs.Add(x); 
       } 
       return xs.ToArray(); 
      })()) 
    { 
    } 
} 

Ancak, şiddetle çünkü bu gerçekten korkunç bakış okunabilirliği açısından pratikte bu kullanılmamasını tavsiye ediyorum. Statik bir yöntemle yapıcı argümanlarını açık bir şekilde iletmeniz gerekir, ancak normalde bunlardan 3-4'ten daha fazlasına sahip değilsiniz.

+0

Pavel, eğer temel sınıf birden fazla kurucu argüman alırsa bunu yapmanın bir yolu var mı? –

+0

Her bağımsız değişken için ayrı bir lambda kullanabilirsiniz, ancak bu lambdalar arasında değişkenleri paylaşamazsınız (yapıcı argümanları hariç). –

+0

Teşekkürler Pavel - bu tam olarak çözmeye çalıştığım sorun ... (lambdas arasındaki değişkenleri paylaşma). Temel olarak, bazı hesaplamaları yapan ve her biri temel sınıfın yapıcısı için ayrı bir parametreyi başlatacak üç farklı (ama ilgili) alan döndüren bir mantığı kapsüllemek istiyorum. Statik yöntem yaklaşımına (söylediğin gibi okunabilir) geri dönerek, bir yapıya dönerek ve her bir parametre için bir kez statik yöntemi çağırarak bu konu üzerinde çalıştım. Bu hacky, ama işe yaradı, çünkü senaryom için statik yöntemlerin çağrılması arasında herhangi bir yan etki yok. –

İlgili konular