31

有人愿意解释这段代码如何产生以下输出吗?

using System;

namespace ConsoleApplication1
{
    class Test
    {
        public override string ToString() { return "ToString override"; }
        public string ToString(string optional = "")
          { return String.Format("ToString with optional parameter {0}", optional); }
    }

    class Test2
    {
        public new string ToString() { return "ToString new"; }
        public string ToString(string optional = "")
          { return String.Format("ToString with optional parameter {0}", optional); }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Test one = new Test();
            Test2 two = new Test2();
            Console.WriteLine(one);
            Console.WriteLine(one.ToString());
            Console.WriteLine(one.ToString("foo"));
            Console.WriteLine("--");
            Console.WriteLine(two);
            Console.WriteLine(two.ToString());
            Console.WriteLine(two.ToString("bar"));
            Console.ReadKey();
        }
    }
}

ToString 覆盖

带有可选参数的 ToString

带有可选参数 foo 的 ToString

--

ConsoleApplication1.Test2

新的 ToString

带有可选参数 bar 的 ToString

4

1 回答 1

50

好的,由于普遍感兴趣,这里有一个快速版本:

Console.WriteLine(一)

这将使用WriteLine(object)重载,而重载将依次执行object.ToString()被覆盖的虚方法One- 因此输出ToString override

Console.WriteLine(one.ToString())

这将查看One并查看哪些方法具有新声明的方法- 折扣覆盖。只有一种这样的方法是适用的——带有可选参数的方法。这样就可以使用默认值执行,导致输出ToString with optional parameter.

Console.WriteLine(one.ToString("foo"))

再次相同,但这次编译器不需要使用默认值,因此ToString with optional parameter foo

Console.WriteLine(二)

同样,这object.ToString()将从WriteLine(object). 该方法尚未被覆盖,因此使用返回类型名称的默认实现,导致输出ConsoleApplication1.Test2.

Console.WriteLine(two.ToString())

编译器查看所有声明的方法,Two其中没有覆盖虚拟方法。在这种情况下,有两种这样的方法——一种是无参数的,另一种是带可选参数的。包含无参数的方法是因为它是的,而不是覆盖基类方法。

无参数方法被认为是“更好”的候选方法,因为编译器更喜欢调用不需要填充任何可选参数的方法。因此输出为ToString new

Console.WriteLine(two.ToString("bar"))

同样,编译器会查看所有声明的方法,Two其中没有覆盖虚拟方法。在这种情况下,有两种这样的方法 - 但无参数的方法不适用,只留下带有可选参数的方法。编译器不需要在这里使用可选参数的默认值,因为它有一个参数......所以输出是ToString with optional parameter bar

有关这方面的更多信息,请阅读 C# 语言规范 - 或者对于中途之家,请参阅我关于重载的文章

于 2012-12-11T17:27:04.857 回答