方法签名中的新关键字
在执行重构时,我最终创build了一个如下例所示的方法。 为简单起见,数据types已被更改。
我以前有一个这样的赋值语句:
MyObject myVar = new MyObject();
这是偶然的重构:
private static new MyObject CreateSomething() { return new MyObject{"Something New"}; }
这是我的一个剪切/粘贴错误的结果,但在new
的private static new
关键字是有效和编译。
问题 : new
关键字在方法签名中意味着什么? 我认为这是在C#3.0中引入的东西?
这与override
有何不同?
来自MSDN的新关键字引用:
MSDN参考
以下是我在Microsoft MVP的networking上find的一个例子,它很有意义: Link to Original
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:
您无法重写非虚拟或静态方法。 重写的基本方法必须是虚拟的,抽象的或重写的。
所以需要使用“新”关键字来“覆盖”非虚拟和静态的方法。
不,这其实不是“新”(原谅双关语)。 它基本上用于“隐藏”一种方法。 IE:
public class Base { public virtual void Method(){} } public class Derived : Base { public new void Method(){} }
如果你这样做:
Base b = new Derived(); b.Method();
Base中的方法是被调用的方法,而不是派生的方法。
更多信息: http : //www.akadia.com/services/dotnet_polymorphism.html
重新编辑:在我给出的例子中,如果您要“覆盖”而不是使用“新”,那么当您调用b.Method(); 派生类的方法将因为多态而被调用。
正如其他人所解释的,它被用来隐藏现有的方法。 这对重写父类中不是虚拟的方法很有用。
请记住,创build“新”成员不是多态的。 如果将对象转换为基types,则不会使用派生types的成员。
如果你有一个基类:
public class BaseClass { public void DoSomething() { } }
然后派生类:
public class DerivedType : BaseClass { public new void DoSomething() {} }
如果声明了一个DerivedType
types然后DerivedType
,方法DoSomething()
不是多态的,它将调用基类的方法,而不是派生的方法。
BaseClass t = new DerivedType(); t.DoSomething();// Calls the "DoSomething()" method of the base class.
从文档:
如果派生类中的方法以new关键字开头,则该方法被定义为独立于基类中的方法。
这在实践中意味着什么:
如果您从另一个类inheritance,并且您拥有共享相同签名的方法,则可以将其定义为“新”,以使其与父类无关。 这意味着如果你有一个对“父”类的引用,那么这个实现将被执行,如果你有一个对子类的引用,那么这个实现将被执行。
就我个人而言,我试图避免使用“新”关键字,因为它通常意味着我的类层次结构错误,但有时候它可能是有用的。 一个地方是版本和向后兼容。
MSDN中有很多这方面的信息。
这意味着该方法将用基类inheritance的相同名称replace一个方法。 在你的情况下,你可能没有在基类中的名称的方法,这意味着新的关键字是完全多余的。
长话短说 – 这不是必需的,它改变了没有行为,这是为了可读性。
这就是为什么在VS中你会看到一些小小的错误,但是你的代码将会被编译和运行,并且和预期的一样。
一个人不得不怀疑是否真的值得创buildnew
关键字,当所有的意思是开发人员承认“是的,我知道我隐藏一个基本的方法,是的,我知道我没有做任何有关virtual
或overriden
(多态) – 我真的想要创build它自己的方法“。
这对我来说有点奇怪,但也许只是因为我来自Java
背景, C#
inheritance和Java
之间存在这种根本区别:在Java
,除非final
指定,否则方法默认为虚拟。 在C#
,默认情况下方法是final / concrete,除非由virtual
指定。
来自MSDN :
使用新的修饰符来显式地隐藏从基类inheritance的成员。 要隐藏inheritance的成员,请使用相同名称在派生类中声明它,并使用新修饰符对其进行修改。
小心这个问题。
您有一个在基类中实现的接口中定义的方法。 然后创build一个隐藏接口方法的派生类,但不要特别声明派生类实现接口。 如果通过对接口的引用调用方法,则将调用基类的方法。 但是,如果你的派生类专门实现了接口,那么它的方法将被称为使用任何types的引用。
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(); } }