Действительно ли возможно переопределить невиртуальный метод?

Потокобезопасность и производительность. Если строка не может быть изменена, это безопасно и быстро для раздавания ссылки среди нескольких потоков. Если бы строки были изменяемы, необходимо было бы всегда копировать все байты строки к новому экземпляру или обеспечивать синхронизацию. Типовое приложение считает строку 100 раз в течение каждого раза, которые представляют в виде строки потребности, которые будут изменены. Посмотрите Википедию на неизменность .

83
задан zfedoran 6 December 2009 в 00:22
поделиться

4 ответа

Нет, вы не можете переопределить невиртуальный метод. Ближайшее, что вы можете сделать, - это скрыть метод, создав новый метод с тем же именем, но это не рекомендуется, так как это нарушает хорошие принципы проектирования.

Но даже скрытие метода ничего вам не даст. полиморфная отправка вызовов методов во время выполнения, как при вызове настоящего виртуального метода. Рассмотрим следующий пример:

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 в этом случае,

104
ответ дан 24 November 2019 в 08:54
поделиться

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

Если метод виртуальный, вы можете переопределить его, используя ключевое слово override в производном классе. Однако невиртуальные методы могут скрыть базовую реализацию только с помощью ключевого слова new вместо ключевого слова override. Невиртуальный маршрут бесполезен, если вызывающий получает доступ к методу через переменную, набранную как базовый тип, поскольку компилятор будет использовать статическую отправку базовому методу (то есть код в производном классе никогда не будет вызван).

2
ответ дан 24 November 2019 в 08:54
поделиться

Если базовый класс не запечатан, вы можете унаследовать от него и написать новый метод, скрывающий базовый (используйте ключевое слово «новый» в объявлении метода). В противном случае нет, вы не можете переопределить его, потому что первоначальные авторы никогда не намеревались его переопределить, поэтому он не виртуальный.

5
ответ дан 24 November 2019 в 08:54
поделиться

Нет, вы не можете.

Вы можете переопределить только виртуальный метод - см. MSDN здесь :

В C # производные классы могут содержать методы с то же имя, что и методы базового класса.

  • Метод базового класса должен быть определен виртуальным.
21
ответ дан 24 November 2019 в 08:54
поделиться
Другие вопросы по тегам:

Похожие вопросы: