【问题标题】:Method Overriding and Optional Parameters方法覆盖和可选参数
【发布时间】:2012-12-11 17:12:34
【问题描述】:

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

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

【问题讨论】:

  • 哪一行不明白? (详细介绍它们会很乏味。)
  • 基本上编译器如何在不同的方法之间进行选择,因为它们具有相同的签名。
  • 他们没有相同的签名...再说一次,如果你说 which 你被困在上面,那会有所帮助。您有多少尝试了解重载解决方案的工作原理?顺便说一句,没有 C# 4.5 这样的东西。
  • 规范中写的。
  • 关于Console.WriteLine(one) 和Console.WriteLine(two) 的部分相当简单。 Console.WriteLine() 接受一个对象。你的Test 类覆盖ToString(),所以你得到一个相当明显的结果。 Test2 不会覆盖ToString(),并且由于WriteLine 正在寻找object,它没有找到new string ToString() 函数。

标签: c# inheritance optional-parameters overriding


【解决方案1】:

好的,因为大家都很感兴趣,这里有一个快速版本:

Console.WriteLine(one)

这将使用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(二)

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

Console.WriteLine(two.ToString())

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

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

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

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

有关这方面的更多信息,请阅读 C# 语言规范 - 或者对于中途的房子,请参阅我的 article on overloading。

【讨论】:

  • 好东西乔恩(像往常一样)。我慢慢地开始着手解决这一切。主要的潜在惊喜点是它在对象上使用object.ToString() 而不是ToString,而且它更喜欢新定义的方法而不是继承的方法。
  • Good Guy Jon Skeet:说“详细介绍所有这些会很乏味”,详细介绍所有这些。
  • 是的,这很有启发性!抱歉,添麻烦了。我和上面的 Chris 一样挂断电话 - object.ToString 解释了一个中的覆盖和两个中的新方法之间的区别,编译器更喜欢新声明的方法这一事实解释了 one.ToString()。
  • 然后说 - 这是一个快速版本。
  • @ananthonline:我没有花时间包含规范参考 :)
猜你喜欢
  • 2017-09-08
  • 2012-02-13
  • 1970-01-01
  • 2018-02-20
  • 1970-01-01
  • 2013-02-02
  • 1970-01-01
  • 1970-01-01
  • 2012-12-21
相关资源
最近更新 更多