2012-10-19 100 views
2

正如每个人都知道在类中使用virtual关键字允许我们在其派生的子类中覆盖它。然而,方法仍然必须坚持相同的签名,例如返回值,参数等。使用虚拟覆盖方法签名

问题:在C#中,我怎样才能重写签名呢?这可能吗?

谢谢。

回答

4

这是不可能的。如果你需要的话,你可以创建一个重载。

编辑

为了使我的情况下对new,请考虑一下,你有一个基本对象的情况下,和一个从它继承。通过在您试图“更改”方法签名的方法之前放置new,您实际上正在浪费四个关键笔划。现在

public class Base { 
    public string Foo() { return null; } 
} 

public class Inherited : Base { 
    public new int Foo() { return 0; } 
} 

Inherited有两种方法:

public string Foo() { return null; } 
public int Foo() { return 0; } 

你实际上并没有改变方法签名。因此,关键字new甚至不需要。你会得到同样的效果没有它:

public class Inherited : Base { 
    public int Foo() { return 0; } 
} 

采用newoverride a non-virtual member of a base class

public class Base { 
    public string Foo() { return null; } 
} 

public class Inherited : Base { 
    public new string Foo() { return "Something else..."; } 
} 

但是你会遇到这个问题,如果你没有注意这个微妙。通过virtual,您可以获得一个虚拟查找表,将您的功能映射到正确的呼叫。用new,你不会。如果您通过Inherited需要Base对象(当然这会起作用),Base类的Foo()将被调用!不,Inherited“覆盖”Foo()

这与重写虚拟成员的行为不同。

public static class MyClass { 
    public string MyMethod (Base @base) { 
     return @base.Foo(); 
    } 
} 

[Test] 
public void then_it_should_return_non_null() { 
    var obj = new Inherited(); 
    var result = MyClass.MyMethod(obj); // obj will get upcasted to Base 
    Assert.That (result, Is.EqualTo(obj.Foo())); // Assert fails! 
} 

[Test] 
public void inherited_should_return_correct_value() 
{ 
    var obj = new Inherited(); 
    var result = obj.Foo(); // will access the "new" method, hiding Base's implementation 
    Assert.That (result, Is.Not.Null); // Assert passes! 
} 
0

您可以用new关键字隐藏旧的实现。但是,基类将无法看到它。

class Base { 
    public string Foo() { } 
} 

class Sub : Base { 
    new public int Foo() { } 
} 

new只在呼叫签名相同时才需要。

+0

虽然这并不会改变签名。 –

+0

@ JamesD'Angelo是的,它可以改变签名。 –

+0

@ JamesD'Angelo http://msdn.microsoft.com/en-us/library/435f1dw2.aspx –

0

到那时,你只是在做一个新的方法。但是,如果你想简单地用新方法签名创建一个新方法,然后调用base.OtherMethod(param1,param2)...你可以。

我想说明的一点是,如果你打算创建具有相同名称的一种方法,在基类,但有一个不同的签名但你还是想仅仅调用基类,然后你可以。

例如:

// In base class - note, the "virtual" isn't necessary. 
public virtual void PostMessage(string message, DateTime entryDate) { ... } 

那你认为......“哦,我想这个基类曾经对自己没有要求的日期是方法的重载......我该怎么办? !”

// In your sub-class. 
public void PostMessage(string message) 
{ 
    base.PostMessage(message, DateTime.Now); 
} 
+0

感谢您的评论。我看到你在说什么,但没有得到最后的声明“,然后调用base.OtherMethod(param1,param2)...你可以。”你能给我一些想法吗? –

+0

我会编辑答案更清晰。 –

0

您正在讨论创建新方法。如果名称相同,但参数不同(返回类型和参数的类型和参数数量),则实际上会超载。