Alex Rivera | Logout

C# optional parameters on overridden methods

Asked 2012-01-18T12:05:50.687
83

Seems like in .NET Framework there is an issue with optional parameters when you override the method. The output of the code below is: "bbb" "aaa" . But the output I'm expecting is: "bbb" "bbb" .Is there a solution for this. I know it can be solved with method overloading but wondering the reason for this. Also the code works fine in Mono.

class Program
{
    class AAA
    {
        public virtual void MyMethod(string s = "aaa")
        {
            Console.WriteLine(s);
        }

        public virtual void MyMethod2()
        {
            MyMethod();
        }
    }

    class BBB : AAA
    {
        public override void MyMethod(string s = "bbb")
        {
            base.MyMethod(s);
        }

        public override void MyMethod2()
        {
            MyMethod();
        }
    }

    static void Main(string[] args)
    {
        BBB asd = new BBB();
        asd.MyMethod();
        asd.MyMethod2();
    }
}
Edit
Report

3 Answers

40

You can disambiguate by calling:

this.MyMethod();

(in MyMethod2())

Whether it is a bug is tricky; it does look inconsistent, though. ReSharper warns you simply not to have changes to the default value in an override, if that helps ;p Of course, ReSharper also tells you the this. is redundant, and offers to remove it for you ... which changes the behaviour - so ReSharper also isn't perfect.

It does look like it could qualify as a compiler bug, I'll grant you. I'd need to look really carefully to be sure... where's Eric when you need him, eh?


Edit:

The key point here is the language spec; let's look at §7.5.3:

For example, the set of candidates for a method invocation does not include methods marked override (§7.4), and methods in a base class are not candidates if any method in a derived class is applicable (§7.6.5.1).

(and indeed §7.4 clearly omits override methods from consideration)

There's some conflict here.... it states that the base methods are not used if there is an applicable method in a derived class - which would lead us to the derived method, but at the same time, it says that methods marked override are not considered.

But, §7.5.1.1 then states:

For virtual methods and indexers defined in classes, the parameter list is picked from the most specific declaration or override of the function member, starting with the static type of the receiver, and searching through its base classes.

and then §7.5.1.2 explains how the values are evaluated at the time of the invoke:

During the run-time processing of a function member invocation (§7.5.4), the expressions or variable references of an argument list are evaluated in order, from left to right, as follows:

...(snip)...

answered 2012-01-18T12:14:15.257
10

Have you tried:

 public override void MyMethod2()
    {
        this.MyMethod();
    }

So you actually tell your program to use the overriden Method.

answered 2012-01-18T12:12:33.907
0

Agree in general with @Marc Gravell.

However, I'd like to mention that the issue is old enough in C++ world (http://www.devx.com/tips/Tip/12737), and the answer looks like "unlike virtual functions, which are resolved at run time, default arguments are resolved statically, that is, at compiled time." So this C# compiler behavior had rather been accepted deliberately due to consistency, despite its unexpectedness, it seems.

answered 2012-10-18T08:38:53.397

Your Answer