2

众所周知,对类中的方法使用 virtual 关键字允许我们在其派生子类中覆盖它。然而,方法仍然必须坚持相同的签名,例如返回值、参数等。

问题:在 C# 中,我如何也可以覆盖签名?这可能吗?

谢谢。

4

4 回答 4

5

这不可能。但是,如果需要,您可以创建一个重载。

编辑

为了让我反对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; }
}

的用途new覆盖基类的非虚拟成员

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! 
}
于 2012-10-19T01:04:03.450 回答
0

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

class Base {
   public string Foo() { }
}

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

new仅当调用签名相同时才需要。

于 2012-10-19T01:04:16.603 回答
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);
}
于 2012-10-19T01:04:35.913 回答
0

您正在谈论创建一种新方法。如果名称相同,但参数不同(返回类型和参数的类型和参数数量),您实际上是在重载。

于 2012-10-19T01:28:09.520 回答