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.

2
  • Possible duplicate: C# optional parameters on overridden methods. Commented Apr 12, 2017 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. Commented Apr 12, 2017 at 11:11

2 Answers 2

5

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.

Sign up to request clarification or add additional context in comments.

3 Comments

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.
@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 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.
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.

2 Comments

No, it's not, doing same thing with text you get same result.
yeah. upper answer is correct. I didn't notice it either but now that I look at it i get same results.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.