4

One of my colleagues find this odd case. I post here a simple example:

using System;

namespace Test
{
    public class F
    {
        public void f(double d) { Console.WriteLine("public void F.f(double d)"); }
        public virtual void f(long l, int q = 0) { Console.WriteLine("public virtual void F.f(long l, int q = 0)"); }
    }

    public class FDerived : F
    {
        public override void f(long l, int q) { Console.WriteLine("public override FDerived.f(long l, int q)"); }
        public void g() { f(2L); }
    }

    public class G : FDerived
    {
        public void h1() { F fd = new FDerived(); fd.f(2L); }
        public void h2() { FDerived fd = new FDerived(); fd.f(2L); }
    }

    class Program
    {
        static void Main(string[] args)
        {
            new FDerived().g();
            new G().h1();
            new G().h2();
            Console.ReadLine();
        }
    }
}

The output of the example is:

public void F.f(double d)
public override FDerived.f(long l, int q)
public void F.f(double d)

I don't see how this can make sense.

Why does f(double) is a better match than f(long, int=0) for f(long)? And why does it depend on the type of 'fd'?!

Valerio
  • 128
  • 8
  • Hint: don't use inheritance unless you really have to... :) – David Arno May 28 '15 at 10:14
  • 1
    Probably a duplicate of http://stackoverflow.com/q/8909811/613130 . Note that if you defined `public override void f(long l, int q = 0) ` in `FDerived` it would work as you wanted. The response to watch is the http://stackoverflow.com/a/8909925/613130 of Marc Gravell – xanatos May 28 '15 at 10:14
  • And to reiterate the first comment on that duplicate question: optional parameters are a code smell. Avoid them even more than inheritance. – David Arno May 28 '15 at 10:20

1 Answers1

5

I don't have the C# Spec here, but optional parameter values aren't inherited by overridden methods.

Try changing in FDerived

public override void f(long l, int q)

to

public override void f(long l, int q = 0)

and it will work as expected.

Note that this can be shown in a simple example:

public class F
{
    public virtual void f(long l, int q = 0) { Console.WriteLine("public virtual void F.f(long l, int q = 0)"); }
}

public class FDerived : F
{
    public override void f(long l, int q) { Console.WriteLine("public override FDerived.f(long l, int q)"); }
}

// Doesn't compile: No overload for method 'f' takes 1 arguments
new FDerived().f(5L);

Clearly this does compile:

new F().f(5L);

and even this one:

F obj = new FDerived();
obj.f(5L);

(this one will output public override FDerived.f(long l, int q))

xanatos
  • 109,618
  • 12
  • 197
  • 280