【问题标题】:How to call base overloaded method in c#?如何在 C# 中调用基重载方法?
【发布时间】:2016-08-25 16:51:31
【问题描述】:

我有以下类层次结构

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

【问题讨论】:

    标签: c#


    【解决方案1】:

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

    【讨论】:

    • 我同意马克的观点。此外,如果您正在考虑在后代类中提供重载方法,请注意这最终可能会使您的类的使用者感到困惑。看看更有效的 C# 中的这一章,标题为避免在基类中定义的重载方法informit.com/articles/article.aspx?p=1570631
    • 哦,我明白了。我想我应该在这里摆脱不必要的复杂性。
    【解决方案2】:

    我会选择这样的:

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

    而不是有 3 个重载方法,它们最终都使用硬编码参数调用相同的方法。

    【讨论】:

    • 如果 OP 使用的是旧版本的语言,那就不好了,但这可能是 C# 4.0 的方式。
    • 值得注意的是,这只对C#/.NET4有效
    • 那太好了,但不幸的是我不仅仅针对 C#4.0
    【解决方案3】:

    您实际上不应该这样做,但有时当您需要廉价的“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...
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-03-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-05
      • 2015-11-22
      • 1970-01-01
      相关资源
      最近更新 更多