Использование модификатора " new " В C#

Я читал, что new modifer скрывает метод базового класса.

using System;

class A
{
    public void Y()
    {
        Console.WriteLine("A.Y");
    }
}

class B : A
{
    public new void Y()
    {
        // This method HIDES A.Y.
        // It is only called through the B type reference.
        Console.WriteLine("B.Y");
    }
}

class Program
{
    static void Main()
    {
        A ref1 = new A(); // Different new
        A ref2 = new B(); // Polymorpishm
        B ref3 = new B();

        ref1.Y();
        ref2.Y(); //Produces A.Y line #xx
        ref3.Y();
    }
}

почему ref2.Y(); производства A.Y как выходные?

Это простой полиморфизм, объект базового класса, указывающий на производный класс, поэтому он должен вызывать функцию производного класса. Я на самом деле Java cum c# coder; эти понятия просто поразили мой ум.

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

ref

3 ответов


в C# методы не являются виртуальными по умолчанию (в отличие от Java). Следовательно,ref2.Y() вызов метода не полиморфные.

чтобы извлечь выгоду из полиморфизма, вы должны отметить A.Y() метод as virtual и B.Y() метод as override.

что new модификатор делает просто скрывает член, который наследуется от базового класса. Вот что действительно происходит в вашем Main() способ:

A ref1 = new A();
A ref2 = new B();
B ref3 = new B();

ref1.Y(); // A.Y
ref2.Y(); // A.Y - hidden method called, no polymorphism
ref3.Y(); // B.Y - new method called

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

при использовании new, класс (или структура, или интерфейс) будет иметь два одинаковые члены, один наследуется от базового типа и один объявлен самим типом. Избегайте этого!

важно: только потому, что вы говорите new, вы не будете "удалять" старый член. Он все еще там, и его легко вызвать. The new member не заменяет унаследованный. Это несвязанный член, который имеет то же имя.

нехорошо иметь два или более членов в типе, который выглядит одинаково. Это приводит к путанице. Рассмотрим код:

interface IOne
{
  void Y();
}
interface ITwo
{
  void Y();
}
interface IBoth : IOne, ITwo
{
}
class Test
{
  static void M(IBoth obj)
  {
    obj.Y();  // must not compile!
  }
}

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

тогда рассмотрим этот код:

interface IBase
{
  void Y();
}
interface IDerived : IBase
{
  /* new */ void Y();
}
class Test
{
  static void M(IDerived obj)
  {
    obj.Y();  // allowed; IDerived has two Y, but one hides the other
  }
}

на этот раз их два Y(), но это вроде как "ближе", чем другой. Поэтому предпочтение отдается ближнему. Однако компилятор выдаст вам предупреждение, если вы не используете new. Если вы используете new, это ничего не меняет, кроме того, что предупреждение о компиляции исчезает. Это действительно плохая идея, чтобы сделать два Y() на цели.

эта ситуация может произойти, если базовый тип (здесь IBase) написано каким-то другим поставщиком. Пример: возможно, вы представили Y() в вашем интерфейсе в то время, когда база не имела этой функциональности. Но тогда поставщик IBase выпускает новую версию своего продукта, где IBase имеет Y(). Теперь, если вы скомпилируете свой код против их новой версии," ваш"Y() все равно будет называться, а не их. Но он даст это предупреждение. Предупреждение уходит, если вы включаете new. Но лучше либо (1) удалить ваш Y() метод полностью, если вы определили, что поставщик Y() выполняет задание или (2) переименовывает ваш Y() метод для некоторого неиспользуемого имени.

если вы хотели полиморфизм, конечно, использовать abstract/virtual (только для членов класса) в сочетании с override (в классе-наследнике). override не будет вводить никаких новых членов, просто новая реализация существующего (унаследованного) члена. Это можно сделать для нестатические члены (обычно методы или свойства) только.


тип объекта-A, но ref2 не имеет доступа к версии Y (), которая определена в классе B, потому что этот метод объявлен с новым модификатором, а не модификатором переопределения. В результате объект ref2 отображает то же описание, что и объект A.