【问题标题】:c# Optional Parameters in a virtual method and overridden methodc#虚拟方法和覆盖方法中的可选参数
【发布时间】:2017-09-08 02:09:17
【问题描述】:

我注意到在使用具有可选参数的虚拟方法时。当您覆盖此方法并为可选参数使用不同的默认值时,它使用原始值。我觉得有点奇怪。

static void Main(string[] args)
{
     List<Piece> Pieces = new List<Piece>();
     Pieces.Add(new Piece());
     Pieces.Add(new Pawn());
     foreach(var v in Pieces)
     {
         Console.WriteLine(v.getPos());
     }
     Console.ReadKey();
}


class Piece
{
    public virtual long getPos(bool enPassant = false)
    {
        if (enPassant)
            return 2;

        return 1;
    }
}


class Pawn:Piece
{
    public override long getPos(bool enPassant = true)
    {
        if (enPassant)
            return 3;

        return 4;
    }
}

最初我希望输出是

1
3

但它会返回

1
4

这意味着它们都是假的。我什至可以将参数重命名为不同的名称,并在方法主体中使用不同的名称,它的行为仍然相同。哪个告诉我默认参数值不能被覆盖,因为这是合同的一部分?显然,如果我将项目转换为 Pawn 对象,然后调用 GetPos(),它会返回 3 而不是 4。

我只是觉得这很有趣,因为我预计它的行为会有所不同。我只是想知道我是否遗漏了任何东西来使这项工作按我的初衷进行。

【问题讨论】:

  • 感觉我必须回答这个问题。您找到了 C# 团队非常不愿意添加对可选参数的支持的原因之一。他们最终屈服于第 4 版,该版本大大改进了对 COM 的支持。可选参数在 Office 等 COM 对象模型中非常常见。但是多态性确实使它成为一个泄漏的抽象,一个 COM 没有的特性,编译器只是不知道在运行时将调用哪个方法。它只能根据它所知道的东西工作,它知道 Piece。

标签: c# overriding virtual


【解决方案1】:

可选参数在编译时在调用点解析。

这意味着v.GetPos() 确实编译为v.GetPos(false),因为v 的类型为Piece。调用是虚拟的并最终被解析为 Pawn.GetPos(bool) 的事实是无关紧要的,这发生在 可选参数已经设置之后。

这就是你得到你所看到的输出的原因。

【讨论】:

  • 感谢您的回复。只是想确保我没有遗漏什么。有道理,我很少使用可选参数,所以我从来没有想过它们在什么时候被解决。
  • @InBetween 这么说,对你来说这听起来像是一个错误吗?当我们为被覆盖的方法设置可选参数默认值时,除了将在代码中分配的这个值之外,我们没有吗?我对这种行为有点感兴趣,我可以找到一些案例,我想要与 Rob 不同的行为。
  • @Leze 不,这不是错误,这是记录在案的行为。 C# 团队从来没有真正想要实现这个功能,这就是为什么它不能很好地与其他语言功能混合的原因之一。直到 C# 的第四个版本,由于大众对使 COM 互操作更容易的广泛需求,他们最终放弃了。
【解决方案2】:

我确实认为是因为触发器。 你做了 v.getPos();没有布尔。 因为没有插入 bool 我认为它的值是标准 false 并且返回 4 istead。

【讨论】:

  • 不,不是,对文本做同样的事情会得到同样的结果。
  • 是的。楼上的答案是正确的。我也没有注意到它,但现在我看着它,我得到了相同的结果。
猜你喜欢
  • 2011-05-21
  • 2018-01-28
  • 1970-01-01
  • 2012-12-21
  • 2013-01-15
  • 2012-02-13
  • 2012-06-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多