views:

164

answers:

2

I've started reading Jon Skeet's early access version of his book, which contains sections on C# 4.0, and one thing struck me. Unfortunately I don't have Visual Studio 2010 available so I thought I'd just ask here instead and see if anyone knew the answer.

If I have the following code, a mixture of existing code, and new code:

public void SomeMethod(Int32 x, Int32 y) { ... }

public void SomeMethod(Int32 x, Int32 y, Int32 z = 0) { ... }

Will the compiler complain either at the definition site or the call site about possible ambiguity?

For instance, what will this piece of code actually do?

SomeClass sc = new SomeClass();
sc.SomeMethod(15, 23);

Will it compile? Will it call the one without the z parameter, or will it call the one with the z parameter?

+4  A: 

It will compile without warnings and will choose the first overload.

With the introduction of optional and named parameters, the overload resolution mechanism of C# has become really complicated. In this specific case, it makes sense however. As usual, the compiler will choose the most specific overload that matches the arguments.

I don't believe this specific case is much different from C# 1.0:

public void SomeMethod(Int32 x, Int32 y) { } 
public void SomeMethod(Int32 x, Int32 y, params Int32[] z) { }

which works identically (in terms of overload resolution).

Follow up answer: I don't think so. I'm afraid you'll have to manually specify the default argument in the method call. However, if x or y parameter had a different name like:

public void SomeMethod(Int32 x, Int32 y) { } 
public void SomeMethod(Int32 t, Int32 y, Int32 z = 0) { }

you could choose the second overload with:

obj.SomeMethod(t: 10, y: 20);
Mehrdad Afshari
Follow-up question: Is there any way to call the second overload without specifying the `z` parameter?
Blixt
+7  A: 

This is covered in the "Overload Resolution" section of the chapter.

When the compiler has two otherwise-equal options to choose from, it will use an overload which doesn't need use any unsupplied optional parameters in preference to one that does, but it's a strict binary choice. If it has to choose between an overload with one unsupplied optional parameter and two, it will consider that to be an ambiguous situation.

To answer your follow-up comment, I don't know any way of forcing an overload with the optional parameter to be used without specifying it. You can't use either of these, for instance:

// Both invalid
sc.SomeMethod(15, 23, );
sc.SomeMethod(15, 23, z:)

If, however, your methods used different parameter names, you could do it then:

public void SomeMethod(Int32 x, Int32 y) { ... }
public void SomeMethod(Int32 a, Int32 b, Int32 c = 0) { ... }

sc.SomeMethod(a: 15, b: 23); // Calls second method
Jon Skeet
Serves me right to jump the bandwagon :)
Lasse V. Karlsen
Jon: are you sure the last line works? I thought you'll have to specify named args *after* all positional args (like in attributes).
Mehrdad Afshari
Oops, yes - editing...
Jon Skeet