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 new

オプションのパラメータバーを備えたToString

4

1 に答える 1

50

さて、一般的な関心があるので、ここに簡単なバージョンがあります:

Console.WriteLine(one)

これはWriteLine(object)オーバーロードを使用し、次に仮想メソッドを実行しobject.ToString()、オーバーライドされOneます-したがって、ToString override

Console.WriteLine(one.ToString())

これはOne、どのメソッドが新しく宣言されたメソッドを持っているかを調べて確認します-割引オーバーライド。適用可能なそのような方法は1つだけです。それは、オプションのパラメーターを使用する方法です。そのため、デフォルト値を使用して実行され、の出力につながりますToString with optional parameter

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

繰り返しますが、今回はコンパイラがデフォルト値を使用する必要がないため、ToString with optional parameter foo

Console.WriteLine(two)

繰り返しますが、これはから仮想object.ToString()メソッドを呼び出しますWriteLine(object)。メソッドはオーバーライドされていないため、型の名前を返すデフォルトの実装が使用され、。が出力されますConsoleApplication1.Test2

Console.WriteLine(two.ToString())

コンパイラーは、仮想メソッドをオーバーライドしTwoいない、宣言されたすべてのメソッドを調べます。この場合、そのような方法は2つあります。パラメーターなしの方法と、オプションのパラメーターを使用する方法です。基本クラスのメソッドをオーバーライドするのではなく、新しいため、パラメーターのないものが含まれています。

パラメータのないメソッドは、コンパイラがオプションのパラメータを入力する必要のないメソッドを呼び出すことを好むため、「より良い」候補と見なされます。したがって、出力は次のようになります。ToString new

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

この場合も、コンパイラは、仮想メソッドをオーバーライドしTwoいない、宣言されたすべてのメソッドを調べます。この場合、そのような方法は2つありますが、パラメーターのない方法は適用できず、オプションのパラメーターを持つ方法だけが残ります。とにかく引数があるので、コンパイラはここでオプションのパラメータのデフォルト値を使用する必要はありません...したがって、出力は次のようになります。ToString with optional parameter bar

これについての詳細は、C#言語仕様をお読みください。または、中途半端な家については、オーバーロードに関する私の記事を参照してください。

于 2012-12-11T17:27:04.857 に答える