3

I have noticed when using a virtual method that has an optional parameter. When you override this method and use a different default value for the optional parameter it uses the original. It seems a bit strange to me.

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;
    }
}

Initially I would expect the output to be

1
3

But it returns

1
4

Which means they are both False. I can even rename the parameter to a different name, and use the different name in the method body and it still behaves the same. Which tells me the default parameter value can't be overridden because that's part of the contract? Obviously if I cast the item to a Pawn object and then call GetPos() it returns a 3 instead of a 4.

I just thought this was interesting as I expected it to behave differently. I was just wondering if I am missing anything to make this work as I originally intended.

Rob
  • 43
  • 6
  • Possible duplicate: [C# optional parameters on overridden methods](http://stackoverflow.com/q/8909811/4252551). – Charlie Apr 12 '17 at 10:45
  • Feels like I have to answer this. You found one reason why the C# team was very reluctant to add support for optional parameters. They finally caved-in at version 4, the one that much improved support for COM. Optional parameters are very common in COM object models like Office. But polymorphism certainly makes it a leaky abstraction, a feature COM does not have, the compiler just doesn't know which method is going to be called at runtime. It can only work from what it does know, it knows Piece. – Hans Passant Apr 12 '17 at 11:11

2 Answers2

4

Optional parameters are resolved at the callsite at compile time.

This means that v.GetPos() is really compiled to v.GetPos(false) because v is typed Piece. The fact that the call is virtual and ends up being resolved to Pawn.GetPos(bool) is irrelevant, that happens after the optional parameter has already been set.

That is why you get the output you are seeing.

InBetween
  • 32,319
  • 3
  • 50
  • 90
  • Thanks for the reply. Just wanted to make sure I wasn't missing something. Makes sense, I've very rarely use optional parameters so I have never thought about at what point they are resolved. – Rob Apr 12 '17 at 13:25
  • @InBetween sayed like that, does it sound like a bug for you? When we sets optionnal parameters default value for overrided method, did we not except that it is this value that will be assign in the code? I am little bit intriged by this comportment, i can found planties of case where i would like the same behavor as it excepted by Rob. – Leze Apr 13 '17 at 07:00
  • @Leze no, it's not a bug, this is the documented behavior. The C# team never really wanted to implement this feature, this is one of the reasons why, it just doesn't mix well with other language features. It wasn't until the fourth version of C# that they finally gave in due to massive popular demand to make COM interop easier. – InBetween Apr 13 '17 at 07:45
0

I do think its because of the trigger. You did v.getPos(); without a bool. because there is no bool inserted I think its the value is standard false and is returning 4 istead.

Davy Quyo
  • 102
  • 6