据我所知.NET Console.WriteLine方法调用类的ToString方法。在下面的代码Console.WriteLine(对象)呼叫和Console.WriteLine(object.ToString())调用产生不同的输出。如果override关键字被加到ToString方法在下面的代码的输出成为相同。但我不知道为什么输出是在第一种情况不同。
程序的输出:
TestOverrideConsole.Program(类名称)
你好从程序
class Program
{
static void Main(string[] args)
{
Program p = new Program();
Console.WriteLine(p);
Console.WriteLine(p.ToString());
Console.ReadLine();
}
public String ToString()
{
return "Hello from Program";
}
}
当你重写一个方法,你基本上把一个新的实现为一个已经被你的基类指定为该方法的“插槽” 1。当你影子的方法(不使用替代),你正在做的是使用你的基类的名称,并指定该名称不同的“槽”。
当编译器执行名称/重载解析,它基本上是试图决定是“插槽”借道方法调用(因为因超载,你可能有多个方法具有相同的名字,但他们将有不同的“槽“S)。
当Console.WriteLine
被编译,编译器可以挑选ToString
唯一的插槽是Object
宣布其ToString
方法之一。所以这是它会永远CALL2的唯一方法。
1I'm使用“插槽”这里是因为,虽然你不会发现它在C#规格使用,只要我还记得,下跌在CLR水平,阴影方法都标有newslot
。
2不100%肯定它字面上叫ToString
本身,而不是通过任何数量的间接性的去,但它不够好这里要说的是它。
Console.WriteLine(p)
调用ToString
对象的方法ToString
方法没有重写。
public String ToString()
此方法隐藏ToString
基类的方法,并且不将其覆盖。这就是为什么输出不同的原因。要正确地覆盖ToString
方法,你必须override关键字添加到方法声明。
我已经修改了代码,以便对其进行编译,您可以inspect it here,
using System;
public static class Program
{
static void Main(string[] args)
{
var p = new P();
Console.WriteLine(p);
Console.WriteLine(p.ToString());
}
}
class P
{
public String ToString()
{
return "Hello from Program";
}
}
你会看到,编译器会发出这样的警告
警告CS0114: 'P.ToString()' 揣继承的成员 'object.ToString()'。为了使当前成员重写该实现,加上override关键字。否则,添加新的关键字。
我认为这是非常自我解释。
当WriteLine()
调用ToString()
它访问虚拟会员,你还没有覆盖。