2010-04-30 46 views

回答

3

的一種方式。所以,你構建的實例,然後調用它調用基類初始化以適當的順序

class MyBase 
{ 
    // Only if need to do some core initialization 
    public MyBase() 
    { 
    } 

    public virtual Initialize() 
    { 
    // do some initialization stuff here 
    } 
} 

class MyDerived : MyBase 
{ 
    // Only if need to do some core initialization 
    public MyDerived() 
    { 
    } 

    public override Initialize() 
    { 
    // do some initialization stuff here 

    // Call the base class initialization function 
    base.Initialize(); 
    } 
} 
+3

如果你去兩次通過創建/初始化,我會建議使用工廠方法或Asbtract Factory來確保初始化語義不會遍佈整個代碼 – LBushkin 2010-04-30 20:03:17

+0

好的,這不完全是我的意思,但它有點幫助我解決問題,ty。 – 2010-04-30 20:10:44

0
class A : B 
{ 
    public A() : base() 
    { 
     base.doSomething(); 
    } 
} 

class B : C 
{ 
    public B() : base() 
    { 

    } 

    public void doSomething() { /* ... */ } 
} 

class C 
{ 
    public C() { /* ... */ } 
} 

執行順序應爲:

  1. Ç::構造函數()
  2. B ::構造函數()
  3. A ::構造函數()
  4. B :: doSomething的( )
+0

正如我所說的,該方法應該在超類中執行,而不是在子類中執行,只是在子類中調用超類方法。 – 2010-04-30 19:56:29

+0

我懷疑OP正在尋找一個解決方案,其中的基類可以確保類型完全實例化後運行一些初始化。否則,每個派生類作者都必須確保調用必要的初始化邏輯。 – LBushkin 2010-04-30 20:02:23

+0

這正是我需要的:( – 2010-04-30 20:08:11

0

我不確定你是什麼意思 - 你不能只是在我們最後一個子類的結尾調用超類的代碼structor?或者,您可以在實例化後直接調用它。

class Program 
    { 
     static void Main(string[] args) 
     { 
      SubSub obj = new SubSub();     
      //obj.DoStuff(); 
      Console.ReadLine(); 
     } 
    } 

    class Super 
    { 
     public Super() 
     { 
      Console.WriteLine("Constructing Super"); 
     } 
     public void DoStuff() 
     { 
      Console.WriteLine("Doin' stuff"); 
     } 
    } 

    class Sub : Super 
    { 
     public Sub() 
     { 
      Console.WriteLine("Constructing Sub"); 
     } 
    } 

    class SubSub : Sub 
    { 
     public SubSub() 
     { 
      Console.WriteLine("Constructing SubSub"); 
      DoStuff(); 
     } 
    } 

這將輸出:實現,這將是去一個兩階段的構造和初始化

Constructing Super 
Constructing Sub 
Constructing SubSub 
Doin' stuff 
+0

我的意思是代碼可以在超類中的對象的完整構造後執行,子類不應該知道它 – 2010-04-30 19:54:31

3

你可以做以下的初始化方法,但它是有風險的(見下面我的編輯):

public class Parent 
{ 
    public Parent() 
    { 
     Initialize(); 
    } 

    protected virtual void Initialize() 
    { 
     // do stuff 
    } 
} 

public class Child : Parent 
{ 
    protected override void Initialize() 
    { 
     // do child stuff 
     base.Initialize(); 
    } 
} 

編輯

正如下面泰倫斯的評論認爲,這是一個危險的做法,因爲在執行Child的構造函數之前Initialize()將被執行。如果在Child的構造函數中有任何字段被初始化,如果它們被Initialize()使用,則它們將不會準備好。這可能會導致令人困惑的錯誤。

一個簡單的解決方案是放棄父母撥打Initialize(),而是讓子類別撥打Initialize()。正如其他人所建議的,另一種選擇是使用抽象工廠模式。

下面是一個使用靜態工廠方法的簡單的解決方案:

class Program 
{ 
    static void Main() 
    { 
     Child.Create(() => new Child(5)); 
     Console.ReadKey(); 
    } 
} 

public abstract class Parent 
{ 
    protected virtual void Initialize() 
    { 
     Console.Write(" is the number."); 
    } 

    public static TChild Create<TChild>(Func<TChild> childGetter) 
     where TChild : Parent 
    { 
     var child = childGetter(); 
     child.Initialize(); 
     return child; 
    } 
} 

public class Child : Parent 
{ 
    private int _number; 

    public Child(int number) 
    { 
     _number = number; 
    } 

    protected override void Initialize() 
    { 
     Console.Write(_number.ToString()); 
     base.Initialize(); 
    } 
} 
+0

這違反了反對調用虛擬從構造方法這種方法會導致難以追查錯誤 參見: http://blogs.msdn.com/b/scottwil/archive/2005/01/14/353177.aspx 和 HTTP ://stackoverflow.com/questions/308061/virtual在超級建構者 – Terrence 2012-11-27 23:26:39

+0

@特雷恩,感謝您的評論。更新了我的答案。 – devuxer 2012-11-28 20:16:13

2

沒有什麼內置到C#語言,可以讓你做到這一點。但是,使用創建模式可以支持它。例如,Abstract Factory模式可能會對您有所幫助。基礎工廠將確保在新創建的基類被實例化爲具體的子類型後調用方法。

+0

你知道溫莎城堡是否有類似的東西? – 2010-04-30 20:11:30

+0

這實際上更像是一個AOP工具的領域,例如PostSharp(現在提醒我應該已經包含在我的答案中),但是Windsor可能會這樣做。從未嘗試過。 – RationalGeek 2010-04-30 20:22:10

相關問題