覆盖方法中的默认参数值

15
在下面的代码中,调用Method2方法时,即使基类根本没有声明参数的默认值,派生类却声明了True作为默认值,Value参数也被传递为False。
可以认为(就像在类似的例子C# optional parameters on overridden methods中所做的那样)编译器首先使用基类的方法声明(这是正确的,因为可以通过在对Method1的调用之前加上this.来更改此行为),但在这种情况下,基类根本没有声明默认值。
对此有合理的解释吗?
using System;

class Base
{
    public virtual bool Method1(bool Value) { return true; }
    public virtual bool Method2(bool Value) { return true; }
}

class Derived : Base
{
    public override bool Method1(bool Value = true)
    {
        return Value;
    }

    public override bool Method2(bool Value = true)
    {
        return Method1();
    }
}

class Program
{
    static void Main(string[] args)
    {
        Derived a = new Derived();
        Console.WriteLine("Call to Method1, expected: True, got: {0}", a.Method1());
        Console.WriteLine("Call to Method2, expected: True, got: {0}", a.Method2());
    }
}

输出结果:

调用Method1,期望值为:True,实际值为:True
调用Method2,期望值为:True,实际值为:False

1
这不是我得到的输出。我得到的是“调用Method1,期望值:True,实际值:True;调用Method2,期望值:True,实际值:True”。你确定你运行的代码完全正确吗?我承认我正在使用C# 5 beta编译器,所以也许已经修复了这个问题... - Jon Skeet
你确定你得到的是这个结果吗?我手头没有C#编译器,但我真的很怀疑——在Method2体内对Method1的调用只能解析为带有默认(true)参数的重写副本。编辑:(换句话说,就是@JonSkeet所说的那样:-)) - Chris Shain
.Net 4.0,我得到了与@andrei相同的结果。 - Austin Salonen
1
回想起来,我很确定我以前见过这个 bug - 在 Stack Overflow 上报告过,并且已经为 C# 5 编译器修复了。嗯。 - Jon Skeet
1
@Andrei:我在谈论这段话:“实际上,情况变得更糟:如果你在Derived中为参数提供了默认值,但在Base中将其设为必填项,则调用M()最终会使用null作为参数值。如果没有其他问题,我会说这证明了它是一个错误:那个null值不能来自任何有效的地方。(这是由于string类型的默认值是null;它总是只使用参数类型的默认值。)” 这正是你正在讨论的内容。你在基类中有一个必填参数,并且你观察到了参数类型的默认值。 - Ben Voigt
显示剩余12条评论
2个回答

1

我刚安装了 Visual Studio 2012 RTM ,即使编译为 Framework 3.5 或 2.0,同样的代码也能正常工作。 因此,显然这是一个编译器问题,而不是 .Net Framework 的问题,并已在新版 C# 编译器中得到修复。


1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接