我有以下类层次结构
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(字符串s,bool标志)内调用的base.M(s)将再次调用B.M(字符串s,bool标志)。
有什么好方法可以避免这种情况吗?
据我所知,如果我调用base.M(s,flag),一切都会起作用,但如果其他人开发了一个衍生类并访问base.M(s)怎么办?我不想在这里留下StackOverflowException的可能性。
解
现在我的层次结构看起来像
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
}
}
答案 0 :(得分:6)
通常这里的诀窍是一个 virtual
(通常是参数最多的那个),这是你唯一一个垂直调用的。其他可能是非虚拟的,只需使用适当的默认值调用“主”。
答案 1 :(得分:2)
我会选择这样的东西:
class A
{
public virtual string M(string s = "", bool flag = false)
{
// Some base logic here
}
}
而不是有3个重载方法,这些方法最终都使用硬编码参数调用相同的方法。
答案 2 :(得分:0)
你不应该这样做,但有时当你需要一个廉价的'hacky'解决方案时,你可以做到以下几点:
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...
}
}