2011-01-29 36 views
4

我已經類層次如何在C#中調用基重載的方法?

class A 
{ 
    public virtual string M() 
    { 
     return M(String.Empty); 
    } 

    public virtual string M(string s) 
    { 
     return M(s, false); 
    } 

    public virtual string M(string s, bool flag) 
    { 
     // Some base logic here 
    } 
} 

class B:A 
{ 
    public override string M(string s, bool flag) 
    { 
     string baseResult = base.M(s); 

     // Derived class logic here 
    } 
} 

中的B類可以在兩種情況下可以使用以下:

1)

A b = new B(); 
string result = b.M(); 

2)

B b2 = new B(); 
string result2 = b2.M(someString, true); 

這兩種情況的碰撞與StackOverflowException。發生這種情況是因爲在B.M(string s,bool flag)中調用的base.M(s)將再次調用B.M(string s,bool flag)。

有什麼好方法可以避免這種情況?我知道如果我調用base.M(s,flag),一切都會起作用,但如果其他人開發一個dervived類並訪問base.M(s)呢?我不喜歡在這裏留下StackOverflowException的可能性。

SOLUTION

現在我的層次看起來像

class A 
{ 
    public string M() 
    { 
     return M(String.Empty, false); 
    } 

    public virtual string M(string s, bool flag) 
    { 
     // Some base logic here 
    } 
} 

class B:A 
{ 
    public override string M(string s, bool flag) 
    { 
     string baseResult = base.M(s, flag); 

     // Derived class logic here 
    } 
} 

回答

6

通常這裏的竅門是有一個virtual(通常是一個與大多數參數),這是唯一一個你垂直呼叫。其他可能是非虛擬的,只需調用具有適當默認值的「主」。

+0

我與馬克同意。另外,如果你正考慮在你的後代類中提供重載方法,請注意,這可能最終導致你的課程消費者感到困惑。看看更有效的C#中的這一章,標題爲避免重載基類中定義的方法http://www.informit.com/articles/article.aspx?p=1570631 – 2011-01-29 09:04:29

+0

哦,我明白了。我想我應該在這裏擺脫不必要的複雜性。 – Aides 2011-01-31 08:22:44

2

我會去像這樣的東西:

class A 
{ 
    public virtual string M(string s = "", bool flag = false) 
    { 
     // Some base logic here 
    } 
} 

,而不是具有3種重載方法,所有最終調用硬編碼參數的方法相同。

0

你真的不應該這樣做,但有時當你需要一個便宜的「哈克」的解決方案,你可以做到以下幾點:

public interface IFooBar 
{ 
    void DoSomething(Object obj); 
} 

public class Foo 
{ 
    public virtual void DoSomething(Object input) 
    { 
     this.DoSomething(input, false); 
    } 

    protected virtual void DoSomething(Object input, bool skipSomeBits) 
    { 
     //Does stuff for Foo and Bar 
     if (!skipSomeBits) 
     { 
      //Does stuff that is specific to Foo but does not need to happen to Bar 
     } 
    } 
} 

public class Bar : Foo 
{ 
    public override void DoSomething(object input) 
    { 
     base.DoSomething(input, true); 
    } 
} 

或(這個比以上更合適),你可以創建虛擬方法兒童(Bar)是空的,並且不調用base但對於父母(Foo)它做的事情:

public interface IFooBar 
{ 
    void DoSomething(Object obj); 
} 

public class Foo 
{ 
    public virtual void DoSomething(Object input) 
    { 
     //Does Foo and Bar stuff 
     this.DoSomething2(input); 
    } 

    protected virtual void DoSomething2(Object input) 
    { 
     //Does Foo stuff 
    } 

} 

public class Bar : Foo 
{ 
    protected override void DoSomething2(Object input) 
    { 
     //Does not call base.DoSomething2() therefore does nothing or can do Bar stuff if needs be... 
    } 
}