方法覆盖和可选参数

pne*_*a08 31 c# inheritance overriding optional-parameters

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

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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

ToString覆盖

带可选参数的ToString

带有可选参数foo的ToString

-

ConsoleApplication1.Test2

ToString新

带可选参数栏的ToString

Jon*_*eet 49

好的,因为有一般的兴趣,这是一个快速版本:

Console.WriteLine(之一)

这将使用WriteLine(object)重载,它将执行object.ToString()虚拟方法,重写One- 因此输出ToString override

Console.WriteLine(one.ToString())

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

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

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

Console.WriteLine(二)

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

Console.WriteLine(two.ToString())

编译器看宣布在所有的方法Two,其重写虚方法.在这种情况下,有两种这样的方法 - 无参数方法和带可选参数的方法.包含无参数的一个因为它是新的而不是覆盖基类方法.

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

Console.WriteLine(two.ToString( "酒吧"))

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

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

  • Good Guy Jon Skeet:说"详细了解所有这些内容将会很乏味",详细介绍了所有这些内容. (71认同)
  • 确实很乏味,但内容丰富,谢谢你写出来 (3认同)
  • 然后说 - 这是一个快速版本.<摇头> (3认同)
  • @ananthonline:我没有花时间包含规范参考:) (3认同)