Новое ключевое слово в сигнатуре метода
Во время выполнения рефакторинга я создал метод, подобный приведенному ниже примеру. Тип данных был изменен для простоты.
У меня раньше была инструкция присваивания:
MyObject myVar = new MyObject();
Он был реорганизован на это случайно:
private static new MyObject CreateSomething()
{
return new MyObject{"Something New"};
}
Это было результатом ошибки вырезания/вставки с моей стороны, но ключевое слово new
в private static new
является допустимым и компилируется.
Вопрос. Что означает ключевое слово new
в сигнатуре метода? Я предполагаю, что это что-то введенное в С# 3.0?
Как это отличается от override
?
Ответы
Ответ 1
Новая ссылка на ключевое слово из MSDN:
Ссылка MSDN
Вот пример, который я нашел в сети от Microsoft MVP, который имел смысл:
Ссылка на оригинал
public class A
{
public virtual void One();
public void Two();
}
public class B : A
{
public override void One();
public new void Two();
}
B b = new B();
A a = b as A;
a.One(); // Calls implementation in B
a.Two(); // Calls implementation in A
b.One(); // Calls implementation in B
b.Two(); // Calls implementation in B
Переопределение можно использовать только в особых случаях. Из MSDN:
Вы не можете переопределить не виртуальные или статический метод. Переопределенная база метод должен быть виртуальным, абстрактным или переопределение.
Поэтому ключевое слово "новое" необходимо, чтобы вы могли "переопределять" не виртуальные и статические методы.
Ответ 2
Нет, это на самом деле не "новое" (простите за каламбур). Он в основном используется для "скрытия" метода. IE:
public class Base
{
public virtual void Method(){}
}
public class Derived : Base
{
public new void Method(){}
}
Если вы сделаете это:
Base b = new Derived();
b.Method();
Метод в базе - это тот, который будет вызываться, а не тот, который был выведен.
Дополнительная информация: http://www.akadia.com/services/dotnet_polymorphism.html
Повторите свое редактирование: В примере, который я дал, если вы должны "переопределить" вместо использования "нового", тогда, когда вы вызываете b.Method(); метод Derived класса будет вызван из-за полиморфизма.
Ответ 3
Как объяснили другие, он используется, чтобы скрыть существующий метод. Это полезно для переопределения метода, который не является виртуальным в родительском классе.
Имейте в виду, что создание "нового" элемента не является полиморфным. Если вы примените объект к базовому типу, он не будет использовать член производного типа.
Если у вас есть базовый класс:
public class BaseClass
{
public void DoSomething() { }
}
И тогда производный класс:
public class DerivedType : BaseClass
{
public new void DoSomething() {}
}
Если вы объявляете тип DerivedType
, а затем выполняете его, метод DoSomething()
не является полиморфным, он будет вызывать метод базового класса, а не производный.
BaseClass t = new DerivedType();
t.DoSomething();// Calls the "DoSomething()" method of the base class.
Ответ 4
Из документов:
Если методу в производном классе предшествует новое ключевое слово, метод определяется как независимый от метода в базовом классе.
Что это означает на практике:
Если вы наследуете другой класс, и у вас есть метод, который использует одну и ту же подпись, вы можете определить ее как "новую", чтобы она не зависела от родительского класса. Это означает, что если у вас есть ссылка на "родительский" класс, тогда эта реализация будет выполнена, если у вас есть ссылка на дочерний класс, тогда эта реализация будет выполнена.
Лично я стараюсь избегать "нового" ключевого слова, так как это обычно означает, что у меня неправильная иерархия классов, но есть моменты, когда это может быть полезно. Одно место - для управления версиями и обратной совместимости.
В MSDN для этого.
Ответ 5
Это означает, что метод заменяет метод с тем же именем, унаследованным базовым классом. В вашем случае у вас, вероятно, нет метода с этим именем в базовом классе, что означает, что новое ключевое слово совершенно лишнее.
Ответ 6
Короче говоря - он НЕ требуется, он изменяет поведение НЕТ, и это ПОЛНОСТЬЮ для читаемости.
Вот почему в VS вы увидите немного squiggly, но ваш код будет компилироваться и работать отлично и, как ожидалось.
Нужно ли задаваться вопросом, действительно ли стоит создавать ключевое слово new
, когда все это означает, что разработчик признает "Да, я знаю, что скрываю базовый метод, да, я знаю, что я не делаю ничего, связанного с virtual
или overriden
(полиморфизм) - я действительно хочу просто создать его собственный метод".
Это немного странно для меня, но, может быть, только потому, что я исхожу из фона Java
и существует это фундаментальное различие между C#
inheritance и Java
: In Java
, методы являются виртуальными по умолчанию, если не указано final
. В C#
методы являются окончательными/конкретными по умолчанию, если не указано virtual
.
Ответ 7
От MSDN:
Используйте новый модификатор, чтобы явно скрыть элемент, унаследованный от базовый класс. Чтобы скрыть унаследованный элемент, объявите его в класс с тем же именем и изменить его с помощью нового модификатора.
Ответ 8
Будьте осторожны в этом.
У вас есть метод, определенный в интерфейсе, который реализован в базовом классе. Затем вы создаете производный класс, который скрывает метод интерфейса, но специально не объявляет производный класс как реализацию интерфейса. Если вы затем вызовете метод с помощью ссылки на интерфейс, будет вызван метод базового класса.
Однако, если ваш производный класс специально реализует интерфейс, тогда его метод будет называться в зависимости от того, какой тип ссылки используется.
interface IMethodToHide
{
string MethodToHide();
}
class BaseWithMethodToHide : IMethodToHide
{
public string MethodToHide()
{
return "BaseWithMethodToHide";
}
}
class DerivedNotImplementingInterface : BaseWithMethodToHide
{
new public string MethodToHide()
{
return "DerivedNotImplementingInterface";
}
}
class DerivedImplementingInterface : BaseWithMethodToHide, IMethodToHide
{
new public string MethodToHide()
{
return "DerivedImplementingInterface";
}
}
class Program
{
static void Main()
{
var oNoI = new DerivedNotImplementingInterface();
IMethodToHide ioNoI = new DerivedNotImplementingInterface();
Console.WriteLine("reference to the object type DerivedNotImplementingInterface calls the method in the class "
+ oNoI.MethodToHide());
// calls DerivedNotImplementingInterface.MethodToHide()
Console.WriteLine("reference to a DerivedNotImplementingInterface object via the interfce IMethodToHide calls the method in the class "
+ ioNoI.MethodToHide());
// calls BaseWithMethodToHide.MethodToHide()
Console.ReadLine();
var oI = new DerivedImplementingInterface();
IMethodToHide ioI = new DerivedImplementingInterface();
Console.WriteLine("reference to the object type DerivedImplementingInterface calls the method in the class "
+ oI.MethodToHide());
// calls DerivedImplementingInterface.MethodToHide()
Console.WriteLine("reference to a DerivedImplementingInterface object via the interfce IMethodToHide calls the method in the class "
+ ioI.MethodToHide());
// calls DerivedImplementingInterface.MethodToHide()
Console.ReadLine();
}
}