Как работает новое ключевое слово в производном классе - PullRequest
4 голосов
/ 22 февраля 2010

У меня некоторая путаница с новым ключевым словом, все работает нормально, когда я использую virtual и override, но немного по-другому с новым (я думаю, что что-то упустил)

 class A
{
    public virtual void Test()
    {
        Console.WriteLine("I am in A");
    }
}

class B:A
{
    public override void Test()
    {
        Console.WriteLine("I am in B");
    }
}


class Program
{
    static void Main(string[] args)
    {
        B b = new B();
        b.Test(); //I am in B
        A a = new B();
        Console.WriteLine(a.GetType()); // Type-B
        a.Test(); //I am in B
       Console.ReadKey();
    }
}

}

Теперь с новым

class A
{
    public  void Test()
    {
        Console.WriteLine("I am in A");
    }
}

class B:A
{
    public new void Test()
    {
        Console.WriteLine("I am in B");
    }
}


class Program
{
    static void Main(string[] args)
    {
        B b = new B();
        b.Test(); //I am in B
        A a = new B();
        Console.WriteLine(a.GetType()); //B
        a.Test(); // I am in A ? why?
       Console.ReadKey();
    }
}

согласно MSDN. При использовании нового ключевого слова новые члены класса вызываются вместо замененных членов базового класса. Эти члены базового класса называются скрытыми, также GetType () отображает тип как B. Так что, где я иду не так, кажется глупой ошибкой: -)

Ответы [ 4 ]

2 голосов
/ 22 февраля 2010

Когда вы скрываете метод базового класса с помощью ключевого слова new, вызов разрешается компилятором, а не во время выполнения.

Поэтому, когда вы пишете a.Test, компилятор вызывает метод Test класса A. Даже если переменная a ссылается на экземпляр B, компилятору все равно, и она по-прежнему вызывает версию A.

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

2 голосов
/ 22 февраля 2010

Ознакомьтесь с описанием Джона Скита n об использовании ключевого слова new. Поскольку a приводится как A, вы вызываете метод A, который нельзя переопределить. Просто у B есть метод с тем же именем.

0 голосов
/ 26 октября 2018

«Новый» означает, что метод «новый», а не «переопределение». Поэтому, если вы вызываете метод с таким именем из базы, он не был переопределен, поэтому производный не будет вызван.

0 голосов
/ 22 февраля 2010

Как правило, после создания дополнительных классов, которые являются производными от A или B, вы обнаружите, что вызов base.Test() вызовет версию A для тех классов, которые override вместо new и те, которые происходят от B, будут иметь версию B, но НЕ A.

...