Затенение на самом деле является языком VB для того, что мы называем сокрытием в C #.
Часто сокрытие (затенение в VB) и переопределение отображаются как в ответе Stormenet .
Показано, что виртуальный метод переопределяется подклассом, и вызовы этого метода даже для типа суперкласса или из внутреннего кода суперкласса вызовут реализацию замены из подкласса.
Затем показывается конкретный метод (не помеченный как виртуальный или абстрактный), который скрывается с помощью ключевого слова new
при определении метода с идентичной подписью в подклассе. В этом случае, когда метод вызывается для типа суперкласса, используется оригинальная реализация, новая реализация доступна только для подкласса.
Однако часто упускается возможность скрыть виртуальный метод.
class A
{
public virtual void DoStuff() { // original implementation }
}
class B : A
{
public new void DoStuff() { //new implementation }
}
B b = new B();
A a = b;
b.DoStuff(); //calls new implementation
a.DoStuff(); //calls original implementation.
Обратите внимание, что в приведенном выше примере DoStuff становится конкретным и не может быть переопределен. Однако можно также использовать оба ключевых слова virtual
и new
.
class A
{
public virtual void DoStuff() { // original implementation }
}
class B : A
{
public new virtual void DoStuff() { //new implementation }
}
class C : B
{
public override void DoStuff() { //replacement implementation }
}
C c = new C();
B b = c;
A a = b;
c.DoStuff(); //calls replacement implementation
b.DoStuff(); //calls replacement implementation
a.DoStuff(); //calls original implementation.
Обратите внимание, что, несмотря на то, что все используемые методы являются виртуальными, переопределение на C не влияет на виртуальный метод на A, поскольку использование new
в B скрывает реализацию A.
Редактировать: В комментариях к этому ответу было отмечено, что вышеупомянутое может быть опасным или, по крайней мере, не особенно полезным. Я бы сказал, да, это может быть опасно и было бы там, если бы это было вообще полезно.
В частности, вы можете столкнуться со всевозможными проблемами, если вы также измените модификаторы доступности. Например: -
public class Foo
{
internal Foo() { }
protected virtual string Thing() { return "foo"; }
}
public class Bar : Foo
{
internal new string Thing() { return "bar"; }
}
Для внешнего наследника Bar
реализация Thing () в Foo
остается доступной и переопределяемой. Все законно и объяснимо в соответствии с правилами типа .NET, тем не менее, совершенно неинтуитивно.
Я опубликовал этот ответ, чтобы углубить понимание того, как все работает, а не как предложение техник, которые можно свободно использовать.