1

这背后的设计原理是什么:

好的:

public class A
{
    public virtual void DoWork() { Console.WriteLine("A"); }
}
public class B : A
{
    private new void DoWork() { Console.WriteLine("B"); } //private works
}
public class C : B
{
    public override void DoWork() { Console.WriteLine("C"); }
}

错误的:

public class A
{
    public virtual void DoWork() { Console.WriteLine("A"); }
}
public class B : A
{
    public new void DoWork() { Console.WriteLine("B"); } //public doesn't
}
public class C : B
{
    public override void DoWork() { Console.WriteLine("C"); }
}

为什么非虚拟方法无论如何都会干扰覆盖虚拟方法?

编辑:更多解释。第一种情况:编译器检查该方法是否为私有(新),因此它允许 C.DoWork() 类覆盖 A.DoWork() 类(不混合虚拟和非虚拟(B.DoWork())方法)。第二种情况:编译器看到声明了 public(new)void 并且它任意(?)破坏了 C 类中的覆盖。现在,如果我想声明 new virtual DoWork() 我可以这样做,如果我想禁止覆盖,我本可以使用密封说明符。但是在这种情况下,我将 public void DoWork() 写为声明正常的非虚拟方法,并且我不希望它像在私有情况下那样参与虚拟继承链。在第二个示例中,我期望:

A ac = new C();
ac.DoWork();

像在私人情况下一样打印 C。

4

3 回答 3

0

在第一个示例中,您的C类 ovverides A DoWorkB具有 DoWork,它是私有的,对子类不可见)。在第二个示例中,您通过非虚拟函数隐藏DoWork并且编译器抱怨您试图覆盖非虚拟函数。解决方案是公开虚函数族。通过new virtual您可以在这些系列之间创建分离。

public class B : A
{
    public new virtual void DoWork() { Console.WriteLine("B"); } //private works
}

然后这段代码

A a = new C();
a.DoWork();

印刷A

B b = new C();
b.DoWork();

印刷C

您可以new virtualKnowing When to Use Override 和 New Keywords中更详细地阅读如何使用。new关键字 withoutvirtual具有不同的语义new virtual,您可以在方法签名中的新关键字中阅读更多信息。

于 2013-01-25T09:42:53.153 回答
0

在下面的代码中

public class A
{
    public virtual void DoWork() { Console.WriteLine("A"); }
}
public class B : A
{
    private new void DoWork() { Console.WriteLine("B"); } //private works
}
public class C : B
{
    public override void DoWork() { Console.WriteLine("C"); }
}

您是在告诉编译器 B 类中的 DoWork() 方法是 A 类new的 DoWork() 方法的一个版本。但是,它允许您override在 C 中使用 DoWork,因为您已new在 B 中将 DoWork 的版本声明为私有,这使得编译器假定该方法未向外界公开。

然而,在这

public class A
{
    public virtual void DoWork() { Console.WriteLine("A"); }
}
public class B : A
{
    public new void DoWork() { Console.WriteLine("B"); } //public
}
public class C : B
{
    public override void DoWork() { Console.WriteLine("C"); }
}

您正在告诉编译器使用override新版本的方法 DoWork(),从编译器的角度来看,这有点错误,因为它不能按照设计语言时设置的规则override使用非abstract//方法virtualoverriden

这就是为什么,我认为,您的代码在一种情况下会出错,而在另一种情况下不会出错。

于 2013-01-25T09:55:13.433 回答
0

因为在第一种情况下,您要覆盖一个A类函数而不是B一个

public class A
{
    public virtual void DoWork() { Console.WriteLine("A"); }
}
public class B : A
{
    private new void DoWork() { Console.WriteLine("B"); } //private works
}
public class C : B
{
    public override void DoWork() { Console.WriteLine("C"); } //OVERRIDES A.DoWork()
}

不能覆盖基类的 virtual/abstract方法。

于 2013-01-25T09:46:48.313 回答