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

MSDN говорит:

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

Пример:

class Base
{
 int value;

 virtual bool Foo()
 {
   value++;
 }
}

class Derived : Base
{
 int value;

 override bool Foo()
 {
  value++;
 }

}

Нужно ли добавлять модификатор new в объявление Derived.value? Какие изменения?


person Captain Comic    schedule 17.12.2009    source источник
comment
NB - я говорю о значении int или новом значении int, а не о Foo()   -  person Captain Comic    schedule 17.12.2009
comment
int — это тип значения, поэтому его не нужно инициализировать с помощью new. Найдите типы значений и ссылочные типы. надеюсь, это поможет   -  person Maciek    schedule 17.12.2009


Ответы (4)


Поскольку поле value равно private, оно недоступно в производном классе. Таким образом, объявление в производном классе ничего толком не скрывает. Вы не должны добавлять new к объявлению. Если вы это сделаете, ничего не изменится, за исключением того, что компилятор предупредит вас о неправильном использовании new. Если поле value было доступно в производном классе (например, это было public), то вы должны были использовать new, чтобы выразить свое намерение скрыть базовый член:

class A {
    public int field;
}
class B : A {
    public int field; // warning. `B.field` hides `A.field`. 
}

Использование new отключит это предупреждение (оно не будет иметь никакого другого эффекта):

class B : A {
    public new int field; // Dear compiler, shut up please.
}

Вы не можете объявить метод как override, так и new. Они взаимоисключающие.

person mmx    schedule 17.12.2009
comment
@Mehrdad Также может быть полезно, если вы укажете пример хорошего места для использования нового модификатора (я бы добавил его ... но я не хочу создавать ответ только для этого). - person Justin Niessner; 17.12.2009
comment
Таким образом, даже если я не использую «новый» модификатор, Derived.Foo() всегда будет обращаться к Derived.value? - person Captain Comic; 17.12.2009
comment
@Captain Comic: Да. Если вы не приведете его к базе явно, как ((Base)this).value. Как правило, new не влияет на сгенерированный код; просто предупреждение компилятора. - person mmx; 17.12.2009

Учитывая ваш пример, Derived.value не «скрывает» Base.value. Модификатор доступа по умолчанию для C# — Private. Если вы сделаете Base.value Public, то да, использование нового модификатора удалит предупреждение.

person Jim H.    schedule 17.12.2009
comment
Разве модификатор доступа по умолчанию не private? - person Broam; 17.12.2009
comment
Модификатор доступа по умолчанию — private для всего, кроме типов, объявленных на уровне namespace, для которых private не имеет смысла, а по умолчанию — internal. - person mmx; 17.12.2009
comment
... и, кстати, вы должны были использовать new, если это было protected. Поле protected видно в его производных классах, и вы бы спрятали его, если объявите поле с таким же именем. - person mmx; 17.12.2009
comment
@Broam: Ах, я думаю, ты прав. vb.net по умолчанию защищен. - person Jim H.; 17.12.2009

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

Основная цель возникает, когда вы используете его для скрытия метода вместо использования переопределения (кстати, чтобы скрыть метод, вы не можете использовать и переопределение, и новое. Это дает вам ошибку, а не просто уменьшение).

Использование модификаторов virtual и override всегда будет похоже на использование модификатора new, за исключением того, что при использовании virtual и override вы не можете вызывать базовый класс, кроме как внутри самого дочернего класса.

person Patrick Desjardins    schedule 17.12.2009

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

Случай, когда вам может понадобиться использовать модификатор new, если базовый метод не помечен как virtual, например:

class Base
{
    int value;

    public void Foo()
    {
        value++;
    }
}

class Derived : Base
{
    int value;

    new public void Foo()
    {
        value--;
    }
}

Кроме того, в приведенном выше примере мы должны предположить, что базовый метод Foo помечен как public или protected, так как в противном случае использование модификатора virtual в любом случае бессмысленно, поскольку он не будет виден базовым/другим классам.

person Justin    schedule 17.12.2009