Что означает "public new virtual void Method()"?

при использовании новых виртуальных ключевых слов для украшения метода? Какая любовь? Как определить интерфейс и добавить класс для наследования интерфейса. но используйте новый виртуальный интерфейс для реализации интерфейса.

 interface IPrinter
{
    void Print();
}

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

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

public class PrinterThree : PrinterTwo
{
    public override void Print()
    {
        Console.WriteLine("PrinterThree.");
    }
}

public class PrinterFour : PrinterThree
{
    public override void Print()
    {
        Console.WriteLine("PrinterFour.");
    }
}

 static void Main(string[] args)
    {
        IPrinter iprinter = new PrinterFour();
        iprinter.Print();//the output is PrinterOne? why???
        Console.ReadLine();
    }

Ответ 1

new и virtual являются двумя (главным образом) не связанными ключевыми словами.

new означает, что он затеняет базовый метод.
virtual позволяет подклассам переопределять его.

Вызов метода через интерфейс приводит к вызову базового метода, поскольку базовый метод не является virtual, а производные классы явно не реализуют интерфейс (что может привести к повторному отображению метода )

Ответ 2

Ключевое слово new, используемое как это, скрывает элемент.

Я никогда не видел, чтобы он использовался в сочетании с ключевым словом virtual, заметьте. Это просто позволяет типы, которые происходят от PrinterTwo до override реализации метода Print.

Используемое ключевое слово new позволяет типу скрывать элементы базовых типов, но только если вы используете переменную самого типа.

Например, если вам нужно:

PrinterOne one = new PrinterTwo();
one.Print();

Он не вызовет метод в PrinterTwo, поскольку он не является частью цепочки наследования.

Что касается того, когда вы это сделаете... когда вам действительно нужно действительно по какой-то нечетной причине, о которой я не могу думать (возможно, отражение?), и вы не можете редактировать код в PrinterOne.

Лично я бы никогда этого не сделал.

Что касается вывода вывода на принтер, то... вызов IPrinter.Print будет вызывать против того типа, в котором он определен (PrinterOne в этом случае), который вернет вас в мой предыдущий пример о new ключевое слово игнорируется, если вы не поговорите с типом, который его использует.

В принципе, использование IPrinter аналогично использованию PrinterOne в моем небольшом примере выше.

Чтобы решить проблему, сделайте метод PrinterOne virtual и полностью удалите использование new virtual в PrinterTwo.

Ответ 3

новый модификатор

http://msdn.microsoft.com/en-us/library/435f1dw2.aspx

При использовании в качестве модификатора новое ключевое слово явно скрывает элемент, унаследованный от базового класса.

Это означает, что метод не переопределяет метод виртуального базового класса, но он по-прежнему имеет приоритет при вызове экземпляра производного класса. Другими словами, новый метод влияет только на переменную производного класса, а не на базовый класс.

виртуальный модификатор

http://msdn.microsoft.com/en-us/library/9fkccyh4.aspx

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

Это означает, что метод может быть переопределен в производном классе. Когда вы вызываете виртуальный метод в переменной базового класса, которая содержит экземпляр производного класса, который переопределил виртуальный метод, вызывается реализация производного класса. Это противоположно поведению нового ключевого слова.

Ответ 4

Это называется методом скрытия. Вы используете это, когда вам нужно предоставить свою собственную реализацию для метода, который нельзя переопределить. Поскольку PrinterOne.Print не является виртуальным методом, его нельзя переопределить. Вместо этого ключевое слово new используется для создания идентичной сигнатуры метода, которая скрывает исходный метод. Вместо этого будет использован новый метод. Добавьте к этому ключевое слово virtual, чтобы ваш новый метод был переопределен, вызывая классы.

Ваш новый метод, скрывающий оригинал, будет вызываться только в том случае, если вы вызываете его через определяющий контейнер (например, PrintTwo). Вызов его интерфейсом вызывает исходный метод. Имейте в виду, что метод никогда не удалялся или не заменялся, поэтому первоначальная реализация все еще существует, напрямую обращаясь к интерфейсу.