2010-02-22 2 views
3

Я имею некоторую путаницу с новым ключевым словом, все работает нормально, когда я использую виртуальные и переопределение, но немного по-другому с новым (я думаю, что я что-то отсутствует)Как новое ключевое слово работает в Dérivé класса

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() показывает тип, как Б. Так где я неправильно, кажется, его глупую ошибку :-)

ответ

2

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

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

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

+1

Это означает, что это время компиляции по сравнению с Runtime..I получил вашу точку, thnx. – Wondering

2

ЗАКАНЧИВАТЬ Jon Skeet's descriptio п использования в new ключевых слов. Поскольку a выбрано как A, вы вызываете метод A, который нельзя переопределить. B просто имеет метод с тем же именем.

+0

thnx для d link – Wondering

0

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

Смежные вопросы