new virtual метод что значит? [дубликат]

251
12 сентября 2021, 14:20
На этот вопрос уже даны ответы здесь:
Чем отличаются override и new (2 ответа)
Закрыт 1 год назад.

Почему в этом случае выведется на экран "A"?

        interface IPrinter
        {
            void Print();
        }
        public class A : IPrinter
        {
            public void Print()
            {
                Console.WriteLine("A");
            }
        }
        public class B : A
        {
            public new virtual void Print()
            {
                Console.WriteLine("B");
            }
        }
        public class C : B
        {
            public override void Print()
            {
                Console.WriteLine("C");
            }
        }
        public class D : C
        {
            public override void Print()
            {
                Console.WriteLine("D");
            }
        }
        internal class Program
        {
            public static void Main(string[] args)
            {
                IPrinter printer = new D();
                printer.Print();
            }
        }
Answer 1

new virtual ничего специально не значит, это просто два модификатора, указанные вместе.

Попробуем разобраться, что происходит в коде.

interface IPrinter
{
    void Print();
}
public class A : IPrinter
{
    public void Print()
    {
        Console.WriteLine("A");
    }
}

Метод A.Print становится реализацией объявления IPrinter.Print, поскольку у него то же имя, те же параметры, и тот же тип возвращаемого значения (void).

Теперь, когда мы приводим объект класса A к типу IPrinter и вызываем Print на самом деле будет вызван A.Print. Этот механизм работает похоже на переопределение виртуальных функций, но он немного сложнее.

Обратите внимание, что поскольку метод A.Print не объявлен как виртуальный, его нельзя переопределить. Его можно только заменить с помощью new.

public class B : A
{
    public new virtual void Print()
    {
        Console.WriteLine("B");
    }
}

Вот здесь метод Print уже объявлен виртуальным, его можно переопределять в наследниках. Но поскольку родительский метод не-виртуальный, мы должны использовать ключевое слово new, чтобы избавиться от предупреждения.

Что означает этот код? То, что поскольку метод A.Print не виртуальный, мы теряем информацию о конкретном типе при приведении к базовому типу.

var b = new B()
b.Print(); // B
var a = b as A;
a.Print(); // A <- B.Print() не переопределяет A.Print(), а заменяет его, поэтому так

Чтобы нужно сделать, чтобы вызов a.Print() печатал B, а не A?

public class A : IPrinter
{
    public virtual void Print()
    {
        Console.WriteLine("A");
    }
}
public class B : A
{
    public override void Print()
    {
        Console.WriteLine("B");
    }
}

Надо объявить метод виртуальным уже в классе A, а в B его переопределить.

Answer 2

В родительском IPrint классе метод Print не override, я уже точно не помню, но помоему чтобы его переопределить, override обязателен, но это не точно)

READ ALSO
Как получить высоту заголовка колонны в dataGridView?

Как получить высоту заголовка колонны в dataGridView?

Ситуация такаяЕсть dataGridView, в котором названия колонн прописываются программно

179
Некорректно отрабатывает транзакция TransactionScope

Некорректно отрабатывает транзакция TransactionScope

Есть 2 связанных таблицыДобавляя запись в одну, во вторую добавляется несколько связанных

133
Обработка событий в ASP.NET MVC

Обработка событий в ASP.NET MVC

У меня в представлении(Formcshtml) есть кнопка: <a href="~/Home/Form" type="button">Ввести данные</a>

132
Неверно отображаются значения C# winforms

Неверно отображаются значения C# winforms

Подскажите новичку в С# что не так, пожалуйстаЕсть форма, в которой заполняются поля 17-значными числами

133