Нет, вы не можете переопределить не виртуальный метод. Самое близкое, что вы можете сделать, - это скрыть метод, создав 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соответствующим образом.