views:

554

answers:

5

I just encountered something with C# today that I hadn't thought of before. I have two methods in my class, one an overload of the other. They are declared like so:

1) public void RequirePermissions(params string[] permissions)...
2) public void RequirePermissions(string message, params string[] permissions)...

In my code, I tried to call the first one like so:

RequirePermissions("Permission1", "Permission2");

...expecting it to call the first overload. Well it called the second overload. The only way I can get it to call the first method in this case is to manually pass a string[] object like so:

RequirePermissions(new string[] { "Permission1", "Permission2" });

Now, this behavior doesn't confuse me because I understand that the compiler can't tell which method I actually wanted to call based on my provided parameters. But was I not careful this could have gone unnoticed in my code. It seems as though Microsoft should have made the compiler throw an error when it encountered a situation like above. Does anyone have any thoughts on this? Is there another way to call the first overload other than the "solution" I posted?

+1  A: 

Yes, I agree it should probably be a warning when using variable length argument arrays causes an ambiguous overload - it's very much an edge case, and people almost certainly don't mean to create such situations.

I also don't know of any way, other than that you posted, to avoid the call resolution that occurs - other than to avoid doing it in the first place, which I would highly recommend!

Adam Wright
+1  A: 

You could not use params and be explicit with your signatures.

public void RequirePermissions(string[] permissions)...
public void RequirePermissions(string message, string[] permissions)..
rick schott
+2  A: 

Agreeing with Adam, I'd change it to something like:

public void RequirePermissions(params string[] permissions)

public void RequirePermissionsWithMessage(string message, params string[] permissions)
scottm
Damn, didn't notice your answer until after I posted mine. Scrollbars in code samples make my eyes glaze over, I guess.
MusiGenesis
great minds think alike, eh?
scottm
@scottm: apparently not. *I* voted *your* answer up. :)
MusiGenesis
+5  A: 

Personally, I'd do it this way:

1) public void RequirePermissions(params string[] permissions)...
2) public void RequireMessageAndPermissions(string message, 
       params string[] permissions)...

People fall too in love with overloading sometimes, and when you combine that with a love for the params keyword, you just increase the confusion level for whomever eventually has to take over your code.

MusiGenesis
+1 Good idea, even more explicit
rick schott
+1  A: 

It looks like there is no other way.

You can find explanation to this behaviour in C# spec http://www.jaggersoft.com/csharp_standard /17.5.1.4.htm and here http://www.jaggersoft.com/csharp_standard/14.4.2.1.htm (paragraph 2)

a parameter array is precisely equivalent to a value parameter (§17.5.1.1) of the same type.

and

The expanded form of a method is available only if the normal form of the method is not applicable and only if a method with the same signature as the expanded form is not already declared in the same type

Andrei Taptunov