在c#中跨越继承边界重载?

Roy*_*mir 7 .net c# clr .net-4.0

看完这篇文章那篇文章后 - 我感到困惑.

它说 :

如果在层次结构的不同级别有两种方法,则首先选择"更深"的方法,即使它不是呼叫的"更好的功能成员".

还 -

事实证明,如果您覆盖子类中的基类方法,则不会将其视为声明它.

现在让我们回到我的问题:

情况1

    public class Base
     {
           public virtual void  Foo(int x)  { "1".Dump();}
     }

    public class Child : Base
     {
          public void Foo(object x) { "3".Dump();}  
          public override void  Foo(int x)  { "2".Dump();}
     }


void Main()
{
    Child c = new Child();
    c.Foo(10); //emits 3
}
Run Code Online (Sandbox Code Playgroud)

好的.根据文章

首先选择"更深"的一个,即使它不是一个"更好的功能.它不计算覆盖...

所以它是正确的,程序发出"3".(Foo(object x)被执行)

让我们改变1行的顺序:

案例2

          public class Base
         {
                 public virtual void  Foo(int x)  { "1".Dump();}
                 public void Foo(object x) { "3".Dump();} //<line being moved here
         }

        public class Child : Base
         {
              public override void  Foo(int x)  { "2".Dump();}
         }


    void Main()
    {
        Child c = new Child();
        c.Foo(10); //emits 2 !!!!
    }
Run Code Online (Sandbox Code Playgroud)

现在它发出"2".

现在让我们将所有int更改为object,将所有对象更改为int:

案例3

      public class Base
    {
      public virtual void  Foo(object x)  { "1".Dump();}
      public void Foo(int x) { "3".Dump();} 
    }

    public class Child : Base
    {
         public override void  Foo(object x)  { "2".Dump();}
    }


void Main()
{
    Child c = new Child();
    c.Foo(1); //emits "3"
}
Run Code Online (Sandbox Code Playgroud)

问题:


问题#1:在案例2中,Child 继承了 Foo(object x)其父亲并且他也覆盖了一个方法.

我们不是这么说的:

事实证明,如果您覆盖子类中的基类方法,则不会将其视为声明它

???

事实上,我们还没有宣布继承的功能......所以这种情况下的规则是什么


问题#2:在案例3中,Child 继承了 Foo(int x)其父亲并且他也覆盖了一个方法.

但现在,他选择了父亲的功能......

它似乎override只有在完全匹配时才会获胜.

再次,这种情况下的规则是什么


Ser*_*kiy 3

请参阅类型 T 中名称 N 的成员查找过程Foo(在您的情况下是类型中的成员Child):

首先,构造 T 中声明的名为 N 的所有可访问(第 3.5 节)成员和 T 的基本类型(第 7.3.1 节)的集合:

virtual void Foo(int x) // Base
void Foo(object x) // Base
override void Foo(int x) // Child
Run Code Online (Sandbox Code Playgroud)

包含 override 修饰符的声明被排除在该集合之外。

virtual void Foo(int x) // Base
void Foo(object x) // Base
Run Code Online (Sandbox Code Playgroud)

参数具有整数类型。所以,这里最好的选择是(参数类型与参数类型匹配)

virtual void Foo(int x) // Base
Run Code Online (Sandbox Code Playgroud)

并且调用了这个方法。但它是虚方法。其调用是由于虚方法调用机制:

对于类中声明或继承的每个虚拟方法,都存在该方法相对于该类的最派生实现。虚拟方法 M 相对于类 R 的最派生实现确定如下:

  • 如果 R 包含 M 的引入虚拟声明,那么这是 M 的最派生实现。
  • 否则,如果 R 包含 M 的重写,那么这是 M 的最派生的实现。
  • 否则,M 相对于 R 的最派生实现与 M 相对于 R 的直接基类的最派生实现相同。

virtual void Foo(int x)相对于类而言,方法的最派生实现是什么Child?是的

override void Foo(int x) // Child
Run Code Online (Sandbox Code Playgroud)

哪个被调用。相同的规则适用于您的第三个示例。但是,当删除重写方法后剩下两个选项时,最佳选择(由于参数类型)是非虚拟方法。