Почему помеченный метод, который скрывает реализацию в базовом классе, может вызывать скрытый метод?

Я немного читал о спецификациях C# и натолкнулся на сценарий, которого не ожидал, и надеялся, что кто-нибудь поделится каким-то осмыслением.

Я наткнулся через new ключевое слово для сокрытия членов базового класса в производном классе, а затем несколько обсуждений о том, когда использовать new в отличие от override на virtual член.

Я добавил небольшой пример кода в мою среду IDE, ожидая увидеть ошибку компиляции

public class BaseType
{
    public void method()
    {
        // do nothing
    }
}
public class DerivedType : BaseType
{
    public new void method()
    {
        base.method();
    }
}

но вместо этого обнаружил, что это законно C#. Так как производный класс скрыл присутствие method()почему мне все еще разрешено это называть?

ура

2 ответа

Решение

DerivedType скрывает метод от классов, которые будут наследовать DerivedTypeи не от себя.
Обратите внимание, что, чтобы скрыть метод, класс должен знать, что в его родительском классе существует метод с тем же именем и теми же аргументами. Следовательно, один класс, скрывающий метод от его собственной области, является нелогичным.

Не смешивайте метод скрытия с методом переопределения. Это два совершенно разных зверя.

Скрывая метод, вы скрываете его только при доступе к методу через тип, который для начала скрывает метод:

public class Foo
{
    public string Blah() { return "Hi from Foo!"; }
}

public class DerivedFoo: Foo
{
    public new string Blah() { return "Hi from DerivedFoo!"; }
}

Теперь у нас следующее поведение:

void TestFoos()
{
    Foo foo = new Foo();
    DerivedFoo derivedFoo = new DerivedFoo();
    Foo derivedFooInDisguise = derivedFoo as Foo;

    Console.WriteLine(foo.Blah()); //Outputs "Hi from Foo!"
    Console.WriteLine(derivedFoo.Blah()); //Outputs "Hi from DerivedFoo!"
    Console.WriteLine(derivedFooInDisguise.Blah()); //Outputs "Hi from Foo!" 
}

Обратите внимание, что это поведение одинаково, даже если Blah объявлен как virtual, Интересная часть - третий звонок. Метод вызывается через Foo типизированный объект. Поскольку это не виртуальный вызов, Foo.Blah() называется, а не DerivedFoo.Blah(),

Теперь это полностью отличается от переопределения метода, когда вызов виртуального метода всегда разрешает тип объекта, а не тип, через который вы его вызываете:

public class Foo
{
    public virtual string Blah() { return "Hi from Foo!"; }
}

public class DerivedFoo: Foo
{
    public override string Blah() { return "Hi from DerivedFoo!"; }
}

Теперь у нас следующее поведение:

void TestFoos()
{
    Foo foo = new Foo();
    DerivedFoo derivedFoo = new DerivedFoo();
    Foo derivedFooInDisguise = derivedFoo as Foo;

    Console.WriteLine(foo.Blah()); //Outputs "Hi from Foo!"
    Console.WriteLine(derivedFoo.Blah()); //Outputs "Hi from DerivedFoo!"
    Console.WriteLine(derivedFooInDisguise.Blah()); ////Outputs "Hi from DerivedFoo!"
} 
Другие вопросы по тегам