基类中的C#-调用方法
我有两门课:基类中的C#-调用方法,c#,.net,inheritance,.net-4.0,polymorphism,C#,.net,Inheritance,.net 4.0,Polymorphism,我有两门课: public class A { public void WriteLine(string toWrite) { Console.WriteLine(toWrite); } } public class B : A { public new void WriteLine(string toWrite) { Console.WriteLine(toWrite + " from B"); } } 在我的代码中,我执行以下操作: B writeClass = new
public class A
{
public void WriteLine(string toWrite) { Console.WriteLine(toWrite); }
}
public class B : A
{
public new void WriteLine(string toWrite) { Console.WriteLine(toWrite + " from B"); }
}
在我的代码中,我执行以下操作:
B writeClass = new B();
writeClass.WriteLine("Output"); // I expect to see 'Output from B'
A otherClass = (A)writeClass;
otherClass.WriteLine("Output"); // I expect to see just 'Output'
我认为这会起作用,因为
但是,它每次都会写入“B的输出”。有没有办法让它按照我想要的方式工作
编辑修复代码示例。在类
B
中重写方法时,不要使用new
关键字。并将A
中的方法声明为virtual
类上的方法是Write,而不是WriteLine。将其更改为相同的名称,它将按照您的预期工作。我刚试过,得到:
Output from B
Output
B的输出
输出
很好地解释了这一点。(这是原始海报链接的较新版本。)该页面显示了派生类重写虚拟成员以及新成员隐藏基类成员的示例
对于新的修改器,似乎存在一些混乱。从:
虽然可以在不使用新修改器的情况下隐藏成员,但是
结果是一个警告。如果使用new显式隐藏成员,则
取消显示此警告并记录以下事实:
该版本旨在作为替代品
请注意,隐藏成员不需要是虚拟的
最佳实践:
- 强烈喜欢覆盖而不是隐藏。多态调用在OO语言中是惯用的
- 如果要隐藏成员,始终使用新修改器
- 永远不要发布带有编译器警告的代码
- 如果团队中的每个开发人员都同意编译器警告无法修复,请取消它
- 当您使用NEW从基类“隐藏”一个方法时,您只是在隐藏它,就是这样。当您明确地调用基类实现时,它仍然被调用
A不包含WriteLine,因此需要修复它。当我把它修好的时候
Output from B
Output
namespace ConsoleApplication11
{
class Program
{
static void Main(string[] args)
{
B writeClass = new B();
writeClass.WriteLine("Output"); // I expect to see 'Output from B'
A otherClass = (A)writeClass;
otherClass.WriteLine("Output"); // I expect to see just 'Output'
Console.ReadKey();
}
}
public class A
{
public void WriteLine(string toWrite) { Console.WriteLine(toWrite); }
}
public class B : A
{
public new void WriteLine(string toWrite) { Console.WriteLine(toWrite + " from B"); }
}
}
“new”关键字使B的WriteLine实现覆盖A的实现
不要接受这个答案,但以我的经验,以这种方式使用“new”关键字几乎总是一个错误。它的可读性较差,而且代码清晰。您的类A有一个写函数,而不是写线
public class A
{
public virtual void WriteLine(string toWrite) { Console.WriteLine(toWrite); }
}
public class B : A
{
public override void WriteLine(string toWrite) { Console.WriteLine(toWrite + " from B"); }
}
首先:我想你想把这两个方法都命名为“WriteLine”,但类A中的方法只命名为“Write”。第二:是的,您从A继承了B,但对象仍然是“B”类型所以现在我不认为你想要什么是可能的。它的
public void WriteLine
notpublic void Write
中的方法应该是WriteLine
而不是Write
?New只是隐藏了基本实现,这样你仍然可以通过从基本实现显式调用基本实现修正了我在LINQPad中的代码示例。输出:Output from B Output
您发布的代码确实具有您在我的机器上期望的输出。如果你的机器上没有这个输出,那么你在编译器中发现了一个bug;请发布您正在使用的编译器的确切版本号,以便我可以尝试在该版本中复制它。新建基本上是为了避免编译器警告。这对执行没有影响。如果他不能将方法设置为虚拟,因为它不是他要修改的基类,该怎么办。然后呢?他必须使用New@DustinDavis-他不必使用新的;他应该用新的。试试看。@TrueWill是的,我知道,但这是不可接受的(至少对我的团队来说)。“我要求使用New来明确这是我们的意图”。@DustinDavis-我们同意这一点。:)我的观点是关键字不会影响行为。我同意尽可能避免使用新关键字,但它的存在不会覆盖实现。它基本上是在抑制编译器警告。在不使用virtual/override的情况下重新说明方法是覆盖实现的原因,但是以非多态的方式(如@DustinDavis所示)。但我认为,两位经验丰富的开发人员对解释其行为的最佳方式表示怀疑,这一事实正好说明了它实际上是多么危险!