代码之家  ›  专栏  ›  技术社区  ›  BCS

这将如何工作?(接口和非虚拟功能)

  •  2
  • BCS  · 技术社区  · 15 年前
    interface I { int J(); }
    
    class A : I
    {
       public  int J(){return 0; }  // note NOT virtual (and I can't change this)
    }
    
    class B : A, I
    {
       new public int J(){return 1; }
    }
    
    
    B b = new B();
    A a = b;
    I ib = b, ia = a;
    
    b.J(); // should give 1
    a.J(); // should give 0 (IMHO)
    
    ia.J(); // ???
    ib.J(); // ???
    

    我知道我可以试试,但我在找一个好的 权威的 整个角落的资料来源,我不想仅仅开始短视地挖掘msdn文本(我不知道谷歌要做什么)。

    3 回复  |  直到 13 年前
        1
  •  1
  •   John Downey    15 年前

    不管您在与基类或接口提供的契约进行对话,它们都将返回1,因为您正在与类B的实例进行对话。

        2
  •  2
  •   STW    15 年前

    改写: 既然我们在讨论实现IDisposable 真的? 重要的是确保派生类和基类都有机会运行各自的清理代码。此示例将涵盖场景的2/3;但是,由于它是从base()派生的,base.dispose()不是虚拟的,因此对((base)child.dispose()的调用将不会为子类提供清理的机会。

    唯一的解决办法是不要从基地获得孩子,但是这已经被排除了。调用((IDisposable)child.Dispose()和child.Dispose()将允许child和base执行其清理代码。

    class Base : IDisposable
    {
        public void Dispose()
        {
            // Base Dispose() logic
        }
    }
    
    class Child : Base, IDisposable
    {
        // public here ensures that Child.Dispose() doesn't resolve to the public Base.Dispose()
        public new void Dispose()
        {
            try
            {
                // Child Dispose() logic
            }
    
            finally
            {
                // ensure that the Base.Dispose() is called
                base.Dispose();
            }
        }
    
        void IDisposable.Dispose()
        {
            // Redirect IDisposable.Dispose() to Child.Dispose()
            Dispose();
        }
    }
    
        3
  •  1
  •   Roman    13 年前

    Jeffrey Richter(clr via c): “C编译器要求实现接口的方法标记为public。 clr要求将接口方法标记为virtual。如果你没有明确的标记 方法在源代码中是虚拟的,编译器将该方法标记为虚拟的和 密封;这将防止派生类重写接口方法。如果你明确 将该方法标记为虚方法,编译器将该方法标记为虚方法(并使其不密封); 这允许派生类重写接口方法“