Нет, вы не можете переопределить не виртуальный метод. Самое близкое, что вы можете сделать, - это скрыть метод, создав new
метод с тем же именем, но это не рекомендуется, поскольку это нарушает принципы хорошего дизайна.
Но даже скрытие метода не даст вам полиморфной диспетчеризации времени выполнения вызовов методов, как при вызове настоящего виртуального метода. Рассмотрим этот пример:
using System;
class Example
{
static void Main()
{
Foo f = new Foo();
f.M();
Foo b = new Bar();
b.M();
}
}
class Foo
{
public void M()
{
Console.WriteLine("Foo.M");
}
}
class Bar : Foo
{
public new void M()
{
Console.WriteLine("Bar.M");
}
}
В этом примере оба вызова M
метода print Foo.M
. Как вы можете видеть , этот подход действительно позволяет иметь новую реализацию метода до тех пор , как ссылка на этот объект имеет правильный производный тип , но скрывает базовый метод делает перерыв полиморфизм.
Я бы порекомендовал вам не скрывать таким образом базовые методы.
Я склоняюсь к сторонникам стандартного поведения C #, согласно которому методы по умолчанию не являются виртуальными (в отличие от Java). Я бы пошел еще дальше и сказал, что классы также должны быть запечатаны по умолчанию. Наследование сложно спроектировать должным образом, и тот факт, что существует метод, который не отмечен как виртуальный, указывает на то, что автор этого метода никогда не намеревался переопределить метод.
Изменить: «полиморфная отправка времени выполнения» :
Под этим я подразумеваю поведение по умолчанию, которое происходит во время выполнения, когда вы вызываете виртуальные методы. Скажем, например, что в моем предыдущем примере кода, вместо определения невиртуального метода, я фактически определил виртуальный метод и истинно переопределенный метод.
Если бы я позвонил b.Foo
в этом случае, CLR правильно определила бы тип объекта, на который b
указывает ссылка, Bar
и отправила бы вызов M
соответствующим образом.