tags:

views:

119

answers:

2

The following code compiles in C# 4.0:

void Foo(params string[] parameters) { }
void Foo(string firstParameter, params string[] parameters) { }

How does the compiler know which overload you're calling? And if it can't, why does the code still compile?

+5  A: 

In some cases, it will decide for you. So, you might want to use different names in cases like this (or in more useful cases :-) ).

In particular, out of the four cases:

        Foo("bar");
        Foo("bar", "bar");
        Foo(new string[]{"bar", "bar"});
        Foo("bar", new string[] { "bar", "bar" });

only #1 and #2 are 'ambiguous' (since #3 and #4 naturally match overload 1 and 2 respectively).

In cases #1 and #2 overload resolution chooses overload #2, because it has a standalone string parameter that matches the only/first parameter of the invocation.

Mau
That actually makes sense.
Oh yes, it does makes sense. I meant it's not very useful to have such 2 overloads.
Mau
+12  A: 

It is well specified in the C# Language Specification, chapter 7.4.3.2, "Better function member":

Otherwise, if MP is applicable in its normal form and MQ has a params array and is applicable only in its expanded form, then MP is better than MQ

Otherwise, if MP has fewer declared parameters than MQ, then MP is better than MQ. This can occur if both methods have params arrays and are applicable only in their expanded forms.

Fwiw, the C# Language Specification is a very readable document and can help you resolve these puzzles by yourself. You have it on your machine, find it back in the Visual Studio install directory (like c:\program files\microsoft visual studio 9.0) in the vc#\specifications\1033 subdirectory.

Another good one is the Ecma-335 standard document, freely available as a PDF download. It specifies the behavior of the CLR and the JIT compiler, great material to understand why C# (and the CLR) do what they do. Recommended.

Hans Passant
Interesting. If I take the OP code and call `Foo("one")` the compiler selects the second method (vs2010, .net 4), which seems wrong according to that quote. The only way that I managed to invoke the first method was to pass a string array as the only argument.
Fredrik Mörk
@Fredrik: my mistake, missed a rule.
Hans Passant
Now it makes more sense :)
Fredrik Mörk
Thanks, I knew about the spec but I don't ever really think about it (if you know what I mean). When I have some time I will look at it so I don't look stupid asking this kind of questions ;-)
Jouke van der Maas
@Jouke, the upvotes you got puts you well past the "dumb question" threshold. OT: how did you end up with a Frisian first name and a river in the South as a last name?
Hans Passant