如何在C#中调用基类重载方法?

4

我有以下类层次结构

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),一切都会正常,但如果其他人开发派生类并访问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
    }
}
3个回答

6
通常的技巧是有一个虚拟的(通常是参数最多的)函数,这是唯一一个垂直调用的函数。其他函数可能是非虚拟的,只需使用适当的默认值调用“主”函数即可。

我同意Marc的观点。此外,如果您正在考虑在您的派生类中提供重载方法,请注意这可能会让使用您类的消费者感到困惑。请参阅《More Effective C#》中的本章,标题为“避免重载基类中定义的方法”http://www.informit.com/articles/article.aspx?p=1570631 - Shiv Kumar
哦,我明白了。我认为我应该在这里摆脱不必要的复杂性。 - Aides

2
我建议使用类似这样的内容:

我会选择像这样的东西:

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

与其拥有三个重载的方法,最终都会以硬编码参数调用同一个方法,不如考虑使用一种更加简化的方式。


如果OP正在使用较旧版本的语言,那么这样做就不好了,但对于C# 4.0来说,这可能是正确的方法。 - Chris Charabaruk
值得注意的是,这仅适用于C#/.NET4。 - spender
那会很好,但不幸的是我不仅针对C#4.0。 - Aides

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...
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接