Как объяснить это поведение с помощью перегруженных и переопределенных методов?
Может ли кто-нибудь быть таким хорошим и объяснить мне, почему этот код показывает Derived.DoWork(double)
. Я могу придумать некоторые объяснения этого поведения, однако я хочу, чтобы кто-то прояснил это для меня.
using System;
public class Base
{
public virtual void DoWork(int param) {
Console.WriteLine("Base.DoWork");
}
}
public class Derived : Base
{
public override void DoWork(int param) {
Console.WriteLine("Derived.DoWork(int)");
}
public void DoWork(double param) {
Console.WriteLine("Derived.DoWork(double)");
}
public static void Main() {
int val = 5;
Derived d = new Derived();
d.DoWork(val);
}
}
Ответы
Ответ 1
Эрик Липперт всегда говорил "Ближе лучше" .
Метод, впервые объявленный в производном классе, ближе, чем метод, впервые объявленный в базовом классе.
Итак, из приведенной выше ссылки производный класс ближе и, следовательно, выбран.
Это поведение тщательно выполняется, чтобы избежать Проблема с хрупким базовым классом
Для полноты я буду делиться пулями:
-
Метод, впервые объявленный в производном классе, ближе, чем метод, впервые объявленный в базовом классе.
-
Метод в вложенном классе ближе, чем метод в содержащем классе.
-
Любой метод типа приема ближе любого метода расширения.
-
Метод расширения, найденный в классе во вложенном пространстве имен, ближе, чем метод расширения, найденный в классе во внешнем пространстве имен.
-
Метод расширения, найденный в классе в текущем пространстве имен, ближе, чем метод расширения, найденный в классе в пространстве имен, указанном директивой using.
-
Метод расширения, найденный в классе в пространстве имен, упомянутом в директиве using, где директива находится в вложенном пространстве имен, ближе, чем метод расширения, найденный в классе в пространстве имен, упомянутом в директиве using, где директива находится во внешнем пространстве имен.
Ответ 2
Это поведение определено в Спецификации языка С#, в частности в разделе 7.5.3 "Разрешение перегрузки". Здесь ссылка на более старую версию, в противном случае обратитесь к языку Specification.docx языка CSharp, который вы должны иметь локально, например C:\Program Files ( x86)\Microsoft Visual Studio 12.0\VС#\Specifications\1033\CSharp Language Specification.docx.
В этом случае исключенные методы отмечены переопределением, поэтому перегрузка double
является единственным допустимым параметром (выделение мое):
Каждый из этих контекстов определяет набор элементов-кандидатов-кандидатов и список аргументов по-своему, как описано в подробно в разделах, перечисленных выше. Например, набор кандидаты на вызов метода не включают методы, отмеченные переопределить (§7.4), а методы в базовом классе не являются кандидатами, если таковые имеются метод в производном классе применим (§7.6.5.1).
Ответ 3
Это, по-видимому, по дизайну:
'При выборе перегрузки, если есть какие-либо совместимые методы, объявленные в производном классе, все сигнатуры, объявленные в базовом классе, игнорируются - даже если они переопределены в одном и том же производном классе! " http://social.msdn.microsoft.com/Forums/vstudio/en-US/a70b25d4-f310-4d06-9dc2-a453f822f4f3/function-not-getting-called-when-overloading-the-function-of-base-class-in-derived-class-with?forum=csharpgeneral