#c# #warnings #virtual-functions
#c# #предупреждения #виртуальные функции
Вопрос:
Возможно, это тонкий момент, но он касается предупреждения, которое выдает компилятор, если вы делаете что-то вроде:
class A
{
public virtual void F() { }
}
class B : A
{
public void F() { }
}
Затем вы получите предупреждение:
'EomApp1.B.F()' hides inherited member 'EomApp1.A.F()'.
To make the current member override that implementation, add the override keyword. Otherwise use the new keyword.
ВОПРОС: Какое предупреждение, на самом деле предупреждающее меня, произойдет, если я ничего с этим не сделаю? Будет ли моя программа функционировать по-другому, если я добавлю ключевое слово ‘new’ или если я этого не сделаю?
(Примечание: Я знаю, что мог бы протестировать это достаточно легко, но я подумал, что стоит спросить здесь)
Ответ №1:
Это ничего не сделает, но используемый вами метод F () также не является полиморфным. Становится очень легко допустить ошибку в коде, если вы начали использовать ссылку на базовый класс, следовательно, вы предупреждены. Конечно, это может быть то, что вы хотите, следовательно, ключевое слово new просто делает его более явным
Например.
B b1 = new B();
b1.F(); // will call B.F()
A b2 = new B();
b2.F(); // will call A.F()
Теперь, если вы добавите класс C
с new
помощью, он будет вести себя так же, как B
. Если вы добавляете класс D
с override
помощью, то F
становится полиморфным:
class C : A
{
public new void F() { }
}
class D : A
{
public override void F() { }
}
// Later
C c1 = new C();
c1.F(); // will call C.F()
A c2 = new C();
c2.F(); // will call A.F()
D d1 = new D();
d1.F(); // will call D.F()
A d2 = new D();
d2.F(); // will call D.F()
Посмотрите на эту скрипку.
Комментарии:
1. Попробуйте это на VS, но я полагаю, что это вызовет A.F ()
Ответ №2:
Нет, поведение по умолчанию точно такое же, как если бы вы использовали new
, за исключением того, выдается ли предупреждение. По моему опыту, вы чаще на самом деле хотите указать override
вместо new
, поскольку обычно это просто случай, когда забывают явно переопределить.
Если вы действительно хотите совершенно отдельный метод, и если у вас есть возможность использовать вместо этого другое имя, я бы выбрал этот подход. Наличие одного метода, скрывающего другой, обычно значительно снижает читаемость IMO. Это не слишком плохо, если цель состоит в том, чтобы просто указать более конкретный возвращаемый тип (и вы убедитесь, что более слабо типизированный метод возвращает то же значение), но это довольно редкий случай.
Ответ №3:
Это просто предупреждение. Код будет работать. При некоторых обстоятельствах это предупреждение может привести к некоторой проблеме.
используйте ключевое слово new с методом, который вы вызываете из базового класса.
class A
{
public virtual void F() { }
}
class B : A
{
new public void F() { }
}
Ссылка
https://msdn.microsoft.com/en-us/library/435f1dw2.aspx
https://msdn.microsoft.com/en-us/library/aa691135 (v = vs.71).aspx