Я недавно наткнулся на то, как компилятор C# разрешает метод вызывает методы, скрывающие методы базовых классов. Я написал следующие тесты, чтобы выставить мою проблему:C# методы сдерживания разрешения элемента во время выполнения
[TestClass]
public class UnitTest1
{
public class Car
{
public int GetNumberOfSeets()
{
return 4;
}
}
public class BmwZ4 : Car
{
public new int GetNumberOfSeets()
{
return 2;
}
}
[TestMethod]
public void TestBmwNumberOfSeets1()
{
BmwZ4 bmw = new BmwZ4();
Assert.AreEqual(2, bmw.GetNumberOfSeets());
}
[TestMethod]
public void TestBmwNumberOfSeets2()
{
var bmw = new BmwZ4();
Assert.AreEqual(2, bmw.GetNumberOfSeets());
}
[TestMethod]
public void TestBmwNumberOfSeets3()
{
Car bmw = new BmwZ4();
Assert.AreEqual(2, bmw.GetNumberOfSeets());
}
}
Удивительно TestBmwNumberOfSeets1 и TestBmwNumberOfSeets2 работают прекрасно, где, как TestBmwNumberOfSeets3 просто не работает.
Может ли кто-нибудь объяснить мне, почему использование автомобиля в качестве принимающего типа (подразумеваемый upcast) превратит мой новый BMW в простой автомобиль?
EDIT: Я понял, что с помощью скрытого механизма метод, который будет вызываться, зависит от типа переменной, вызывающей метод. Динамической отправки нет. Но почему? Компилятору было бы легко использовать динамический тип вместо статически объявленного.
Скрывающий механизм в моем сознании должен использоваться, когда нужно переопределить класс, который не запечатан и не принадлежит ему (с использованием стороннего API), и хочет создать собственное поведение для метода, который является не отмечено виртуальным. Это главная цель. Но если у вас нет динамической отправки, функция абсолютно бесполезна и очень опасна для использования.
Потому что вы скрываете метод, не перекрывая его. Поскольку метод не является виртуальным, вы не получаете динамическую отправку, поэтому метод, который вы получаете, определяется тем, что у вас есть: 'Car'. – Blorgbeard
НИКОГДА не используйте ключевое слово new, потому что поведение, которое вы продемонстрировали, - это то, что вы получаете в результате. Метод называется изменением в зависимости от типа переменной, используемой для ссылки на экземпляр подкласса, используя применение нового модификатора к методу базового класса. Это чрезвычайно опасный код, особенно в руках вашего среднего разработчика, который не понимает нюансов языка C#. – Mick
Я знаю, что это плохая привычка использовать скрытый механизм над наследованием. Но я использовал его, потому что имел дело с кодом, который не принадлежит мне, что является именно тем случаем использования этой функции языка. Но я согласен, что НИКОГДА не буду использовать его снова. Это сломанная функция! –