15

In the following code, call to Method2 receives the Value parameter as False, even though base class does not declare default value for the parameter at all, and derived class declares True as default.
It could be argued (as was done in similar example here: C# optional parameters on overridden methods) that the compiler uses base class's method declaration first (which is true, as this behavior can be changed by prefixing call to Method1 with this.), but in this case, the base does not declare default value at all.
Is there a rational explanation for 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());
    }
}

Output:

Call to Method1, expected: True, got: True
Call to Method2, expected: True, got: False
Community
  • 1
  • 1
Andrei
  • 1,015
  • 1
  • 11
  • 19
  • 1
    That's not the output I get. I get "Call to Method1, expected: True, got: True Call to Method2, expected: True, got: True". Are you sure that's *exactly* the code you're running? Admittedly I'm using the C# 5 beta compiler, so maybe that's been fixed... – Jon Skeet Aug 07 '12 at 21:06
  • Er- are you sure that's what you get? I dont have a C# compiler in front of me, but I really tend to doubt it- the call to `Method1` in the body of `Method2` could only resolve to the overridden copy with the defaulted (true) param. EDIT: (In other words, what @JonSkeet said :-) ) – Chris Shain Aug 07 '12 at 21:06
  • .Net 4.0 and I get the same result as @andrei. – Austin Salonen Aug 07 '12 at 21:08
  • 1
    Thinking back, I'm pretty sure I've seen this bug before - reported here on Stack Overflow, and fixed for the C# 5 compiler. Hmm. – Jon Skeet Aug 07 '12 at 21:08
  • I also get the same result as @andrei ... Very odd! – StoriKnow Aug 07 '12 at 21:10
  • @Jon: This question has a link to the old one. – Ben Voigt Aug 07 '12 at 21:10
  • This is exactly the code I run and the result I get. I tried running it under framework versions 2.0, 3.5, 4.0.Have not tried beta 4.5 or 5.0. – Andrei Aug 07 '12 at 21:10
  • possible duplicate of [C# optional parameters on overridden methods](http://stackoverflow.com/questions/8909811/c-sharp-optional-parameters-on-overridden-methods) -- Look at Jon's answer, which already details the behavior when the base class doesn't have a default argument (he calls it "mandatory"). – Ben Voigt Aug 07 '12 at 21:11
  • @BenVoigt: Ah yes. I looked just at the start of that, and the accepted answer (which I disagree with), but didn't recognize it. – Jon Skeet Aug 07 '12 at 21:12
  • Good to see it looks like it's fixed for C# 5 though. Maybe I should go back through the mails I've sent Eric and check for changes ;) – Jon Skeet Aug 07 '12 at 21:13
  • Interestingly, if I change bool to string in the above code, I get null instead of the default string. – Vlad Aug 07 '12 at 21:13
  • @Ben I actually referenced that in my question. I don't consider this a duplicate since in my example the base does not declare default value, and the value returned (false) is not expected from either base or derived implementation. – Andrei Aug 07 '12 at 21:13
  • @Andrei: Like I commented, go read Jon's answer on that question. He covered this case quite completely. – Ben Voigt Aug 07 '12 at 21:16
  • @BenVoigt I did read Jon's answer, it's very thorough, but the difference with that example is that "false" is not default value here and should never be produced. It should be either mandatory or "true". Note: signature of the call to Method1 from inside Method2 does not match base class's declaration, since the parameter is not optional in the base class. – Andrei Aug 07 '12 at 21:23
  • 1
    @Andrei: I'm talking about this paragraph: "Indeed, it gets worse: if you provide a default value for the parameter in `Derived` but make it mandatory in `Base`, the call `M()` ends up using `null` as the argument value. If nothing else, I'd say that proves it's a bug: that null value can't come from anywhere valid. (It's `null` due to that being the default value of the `string` type; it always just uses the default value for the parameter type.)" Exactly what you are discussing. You have a mandatory parameter in the base class, and you are observing the default value of the parameter type – Ben Voigt Aug 07 '12 at 21:51
  • @BenVoigt Thank you, I did miss that part – Andrei Aug 07 '12 at 22:02
  • It seem that this question is related to another question: http://stackoverflow.com/questions/7474364/ambiguity-with-inheriting-an-optional-parameter-base-method – Ray 'user1578904' Aug 08 '12 at 14:27

2 Answers2

1

Looks like this is a type of bug.

Here is the link you guys were talking about, I think its from earlier this year:

C# optional parameters on overridden methods

Community
  • 1
  • 1
LOZ
  • 1,169
  • 2
  • 16
  • 43
1

I just installed Visual Studio 2012 RTM and the same code is working as expected even when compiled for Framework 3.5 or 2.0. So apparently this is a compiler issue, rather than .Net Framework one and has been fixed in the new version of the C# compiler.

Andrei
  • 1,015
  • 1
  • 11
  • 19