CLR调用一个类型的实例方法时会先判断这个方式是否是可被重写的虚方法,如果只是普通方法,那就直接调用,如果是虚方法,那就在继承链上查找实际类型的最终重写版本。复现一下这个过程,调用类型A的show()方法,先查找是否是虚方法,
第一种情况不是虚方法,那么直接调用A的show()方法
第二种情况发现了A的show方法是virtual,可重写的,那么就在继承链上找到A的实际类型C的该方法最终重写版本,也就是B重写的Show()方法。

解决方案 »

  1.   

    在一本设计模式的书(名字记不得了,白色带粉红色封皮的,人民邮电的)中有一段很精彩的话,他说,继承的本质还是封装。我们用这个思维方式把继承和字段的Scope做一个类比:比如
    class A
    {
        int X;
    }
    作为OO语言的一种设计准则,如果你不明确它是公开的,编译器倾向视作它是私有的。比如int X,虽然X没有加上任何修饰,但是它实际上是private而不是public的。这段代码等价
    class A
    {
        private X;
    }
    那么我们看如下代码
    class A
    {
        public void Foo() { ... }
    }
    我们没有加上任何关于它是否能够重写的修饰,那么编译器绝对不允许它被重写
    它等价
    class A
    {
        public sealed void foo() { ... }
    }
    如果我们需要让X对外可见,我们必须写
    public int X;
    一样的道理,如果我们要让foo()可以被重写,我们必须写
    public virtual void foo() { ... }
    我们看下什么是new。
    我们看一个极端的例子:
    class A
    {
        private int X;
        public void foo()
        {
            int X = 1;
            this.X = 2;
        }
    }
    我们故意定义了一个和成员变量X一样的局部变量X,那么我们需要一种机制确保它们都可以访问到,但是你要知道,这两个X完全没有一毛钱的关系。
    类似的
    class A
    {
        public void foo() { ... }
    }
    class B
    {
        public void foo() { ... }
    }
    此时A.foo()和B.foo()也没有一毛钱的关系,这个能理解么?
    那么如果是
    class B : A
    {
        public void foo() { ... }
    }
    呢?
    仍然没有一毛钱的关系。
    但是此时B拥有了两个没有一毛钱关系的foo()方法, 一个是自身定义的,一个是从A继承来的。
    而new其实就是解决这种冲突的一种机制。
    b.foo()表示B的那个
    (b as A).foo()表示A的那个
    就好比前面的代码中两个X变量也毫无关系一样。现在你应该理解,new和virtual根本风马牛不相及。可是被脑残的部分天朝教师硬是扯在一起讲。