Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/296.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用虚拟签名重写方法签名_C# - Fatal编程技术网

C# 使用虚拟签名重写方法签名

C# 使用虚拟签名重写方法签名,c#,C#,众所周知,对类中的方法使用virtual关键字允许我们在其派生的子类中重写它。然而,方法仍然必须坚持相同的签名,例如返回值、参数等 问题:在C#中,我如何也覆盖签名?这可能吗 谢谢。这是不可能的。但是,如果需要,可以创建重载 编辑 让我反对新< /代码>,请考虑有一个基类对象和一个继承它的情况。通过将new放在试图“更改”方法签名的方法之前,实际上浪费了四个按键 public class Base { public string Foo () { return null; } } pu

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

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


谢谢。

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

编辑

让我反对<代码>新< /代码>,请考虑有一个基类对象和一个继承它的情况。通过将

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
的用途是:

但如果你不注意这个微妙之处,你会遇到问题。使用
virtual
您将获得一个虚拟查找表,该表将把您的函数映射到正确的调用。使用
new
,您将不会。如果在需要
Base
对象的地方传入
Inherited
(当然这会起作用),将调用
Base
类的
Foo()
!不是,继承了
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! 
}

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

class Base {
   public string Foo() { }
}

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

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

此时您只是在创建一个新方法。但是,如果您只想创建一个具有新方法签名的新方法,然后调用base.OtherMethod(param1,param2)。。。你可以

我想指出的一点是,如果您打算创建一个与基类同名但签名不同的方法,但仍然希望调用基类,那么您可以

例如:

// In base class - note, the "virtual" isn't necessary.
public virtual void PostMessage(string message, DateTime entryDate) { ... }
然后你想。。。“哦,伙计,我希望这个基类有一个不需要日期的方法重载…我能做什么?!”


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

这不会更改签名。@JamesD'Angelo是的,它可以更改签名。它不会更改签名。它覆盖了一个非虚拟类成员。快速检查VS中的健全性会给我一个警告:“成员'foo.bar()'不会隐藏继承的成员。新关键字不是必需的。”@JamesD'Angelo它们是公共的吗?谢谢你的评论。我明白你的意思,但没有得到最后一句话“然后调用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);
}