【问题标题】:Force calling the base method from outside a derived class强制从派生类外部调用基方法
【发布时间】:2009-01-13 04:05:24
【问题描述】:

我有两个班级:

public class MyBase
{
    public virtual void DoMe()
    {

    }
}

public class MyDerived:MyBase
{
    public override void DoMe()
    {
        throw  new NotImplementedException();
    }
}

我有以下代码来实例化 MyDerived:

        MyDerived myDerived=new MyDerived();

问题是如何调用基类的DoMe?如果我使用 myDerived.DoMe(),那么将调用派生方法,从而导致异常。我尝试将 myDerived 转换为 MyBase,但它仍然是被调用的方法的派生版本。

编辑:如以下评论中所述,我无法更改 MyDerived 或 MyBase,因为它们不是我的代码。

【问题讨论】:

  • 这是对封装和信息隐藏的彻底黑客攻击,我认为没有真正的答案。虽然不确定反射......

标签: c# inheritance overriding


【解决方案1】:

有一个解决方案,但很丑:使用反射来获取基类方法,然后发出调用它所需的 IL。查看this blog post,它说明了如何执行此操作。当我所拥有的只是对覆盖该方法的派生类的引用时,我已经成功地使用这种方法来调用基类的方法实现。

【讨论】:

    【解决方案2】:

    你不能调用基类版本。

    如果该方法在派生类上不起作用,那么在派生类的实例上调用该方法的基本版本就不太可能起作用。那只是自找麻烦。该类并非旨在以这种方式工作,您尝试做的事情可能只会导致该类的其他部分行为不可预测。

    当对象直接告诉你它不起作用时,为什么你需要在对象上调用这个方法?

    在我看来,这些类有一些设计缺陷,如果你不被允许更改类,也许你可以改用设计更好的库。

    【讨论】:

      【解决方案3】:

      要从外部类调用 MyBase.DoMe(),您需要 MyBase 的实例或不覆盖 DoMe() 的派生实例。声明为虚拟的方法将在对象的实际运行时类型上调用,而不是对象的类型,这就是为什么转换为 MyBase 不会改变调用的方法的原因。但是,如果该方法未在 MyBase 中声明为 virtual 并且 MyDerived 仍然实现 DoMe() ,它将“隐藏” MyBase 的实现。因此,如果引用是 MyDerived,它将调用 MyDerived.DoMe(),但在这种情况下,转换为 MyBase myBase = (MyBase)myDerived,然后调用 myBase.DoMe() 将调用 MyBase.DoMe()。

      【讨论】:

      • 是否可以将 MyDerived 转换为 MyBase 并进行调用?我不能选择不覆盖 DoMe(),因为 MyBase 和 MyDerived 都不是我的代码。
      • 如果您无法控制 MyDerived 或 MyBase,我看到的唯一选择是创建 MyBase 的实例或创建您自己的类,该类从 MyBase 派生并提供您想要的功能。
      • 我想知道它是否可以做类似的事情:base.base.DoMe()
      • 大声笑,不能。四年前,斯基特回答了这个问题。
      【解决方案4】:

      派生类不需要提供方法的实现。删除它,默认会调用基类中的实现。

      如果与您的示例不同,基类中的方法是抽象的,并且您必须提供一个实现,但派生类提供一个实现是没有意义的,那么类的设计可能有问题。

      【讨论】:

        【解决方案5】:
        public class MyDerived:MyBase{    
            public override void DoMe()    
            {        
                base.DoMe();
            }
        }
        

        编辑:

        如果不通过子类方法,您无法从“外部”访问基类方法。您唯一的选择是直接实例化您的基类并调用它的方法。

        MyBase mb = new MyBase();
        mb.DoMe();
        

        【讨论】:

        • 派生类中可以访问基类方法,但是想从外部访问。
        【解决方案6】:

        鉴于您的限制,还有另一种可能性:

        下载 .Net Reflector。反编译现有代码,然后进行任何您需要的更改以支持您的情况。

        当然,在继续之前,请检查其合法性。

        【讨论】:

          【解决方案7】:

          这个问题太老了,但我没有看到以下选项:

          您可以使用“new”关键字来指定重叠方法。然后,您只需将其转换为您希望调用其方法的类。

              public class MyBase
              {
                  public virtual void DoMe()
                  {
          
                  }
              }
          
              public class MyDerived:MyBase
              {
          //note the use of 'new' and not 'override'
                  public new void DoMe()
                  {
                      throw  new NotImplementedException();
                  }
              }
          

          实施

          var myDerived = new MyDerived();
          var derivedDoMe = myDerived.DoMe();
          var baseDoMe = ((MyBase)myDerived).DoMe();
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2010-12-26
            • 2014-03-17
            • 2011-05-11
            • 2016-07-06
            • 2014-02-15
            • 2013-03-28
            • 2013-04-11
            • 1970-01-01
            相关资源
            最近更新 更多