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