Подтвердить что ты не робот

Переопределение метода и дополнительные параметры

Кто-нибудь захочет объяснить, как этот код создает выходной результат?

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 с необязательным параметром

ToString с необязательным параметром foo

-

ConsoleApplication1.Test2

ToString new

ToString с необязательной парой параметров

4b9b3361

Ответ 1

Хорошо, так как здесь общий интерес, здесь быстрая версия:

еЫп (один)

Это будет использовать перегрузку WriteLine(object), которая, в свою очередь, будет выполнять виртуальный метод object.ToString(), переопределенный в One - следовательно, вывод ToString override

еЫп (one.ToString())

Это рассмотрит One и посмотрит, какие методы имеют новые объявленные методы - переопределение переоценки. Существует только один такой метод, который применим - тот, который имеет необязательный параметр. Таким образом, выполнение выполняется с использованием значения по умолчанию, что приводит к выводу ToString with optional parameter.

еЫп (one.ToString( "Foo" ))

То же самое, но на этот раз компилятору не нужно использовать значение по умолчанию, поэтому ToString with optional parameter foo

еЫп (два)

Опять же, это вызовет виртуальный object.ToString() метод из WriteLine(object). Метод не был переопределен, поэтому используется реализация по умолчанию, возвращающая имя типа, что приводит к выводу ConsoleApplication1.Test2.

еЫп (two.ToString())

Компилятор просматривает весь метод, объявленный в Two, который не переопределяет виртуальные методы. В этом случае существует два таких метода - без параметров и один с необязательным параметром. Параметр без параметров включается, потому что он является новым, а не переопределяет метод базового класса.

Метод без параметров считается "лучшим" кандидатом, потому что компилятор предпочитает называть метод, который не требует заполнения каких-либо дополнительных параметров. Следовательно, вывод ToString new

еЫп (two.ToString( "бар" ))

Опять же, компилятор просматривает весь метод, объявленный в Two, который не переопределяет виртуальные методы. В этом случае существует два таких метода - но беззадачный не применим, оставив только тот, у которого есть необязательный параметр. Компилятору не нужно использовать значение по умолчанию для необязательного параметра здесь, так как он получил аргумент в любом случае... так что вывод ToString with optional parameter bar

Более подробно об этом читайте в спецификации языка С# или в доме с половиной пути, см. статью о перегрузке.