When Method Overloading Goes Haywire

Let's say you have the following code:

public class ParameterOne { }

public class ParameterTwo { }

public static class OverloadedParamsIssue
{
    public static void CallOne(Guid value, params ParameterOne[] parameters) { }

    public static void CallOne(Guid value, params ParameterTwo[] parameters) { }
}

Now...how do you call it?

OverloadedParamsIssue.CallOne(Guid.NewGuid());

This gives the following error:

Error 1 The call is ambiguous between the following methods or properties: 'Playground.OverloadedParamsIssue.CallOne(System.Guid, params Playground.ParameterOne[])' and 'Playground.OverloadedParamsIssue.CallOne(System.Guid, params Playground.ParameterTwo[])'

Big deal, right? Well, this is the same issue that's currently in the Expression class:

public static ListInitExpression ListInit(NewExpression newExpression, params ElementInit[] initializers);
public static ListInitExpression ListInit(NewExpression newExpression, params Expression[] initializers);

I found out about this when I was trying out Jomo's code for visiting expression trees. If you copy the code and try to run it, you'll get an error similar to this. To fix it, I can do this:

Expression.ListInit(lin, (Expression[])null)

which will get the code to compile...but it's ugly, and it won't work. I dug into Reflector to look at the method implementations and it says it will throw an error if the array in either method is null. Damn! That actually seems to violate the spirit of the params keyword, in that the values are optional if the argument is a params array.

On a whim, I tried this:

Expression.ListInit(lin, li.Initializers)

and that seems to work.

The "correct" fix IMHO is that the Expression class should have not had the array parameters optional, or provided another overload that just took one parameter. But if you add that extra overloaded method, then you're saying that other two methods really should not be params-based.

The moral of the story is, be really careful when you're overloading methods that use params. And if you're going to use params, make sure that the values are really optional!

* Posted at 02.24.2009 12:51:01 PM (Last Update: 03.05.2009 01:12:10 PM) | 4 comments | Link | RSS *

Comments

# how about this..., from Justin Chase at 02.24.2009 02:22:52 PM

Expression.ListInit(lin, new Expression[]{})

# Would work, but..., from Jason Bock at 02.24.2009 02:29:53 PM

Justin,

That's creating an array for no good reason. Anyway, the real issue that the API is a little faulty IMO. They're not optional parameters if you look at the underlying implementation.

# Possible feature, from Daniel Earwicker at 03.05.2009 09:29:19 AM

One way of spinning this is to call it a feature (of the language, not the Expression class). Suppose I'd like to enforce at compile time that the caller should pass at least one argument to my variable args list. All I need do is add a dummy method with the same name and same fixed arguments, followed by a variable arg list params int[] (to pick a type at random). The presence of that method will cause the ambiguity error. (Of course it doesn't completely stop the user passing an empty array if they want to because they can just explicitly new up an empty array.)

# Would work, from wwww at 03.05.2009 01:12:08 PM

The "correct" fix IMHO is that the Expression class should have not had the array parameters optional, or provided another overload that just took one parameter. But if you add that extra overloaded method, then you're saying that other two methods really should not be params-based.
http://ebs-software.net

Add a Comment

(*) = Required field
Name (*):

E-Mail (*):

Web Site:

Title (*):

Comments (*):

Enter the code you see (*)



Quote
"Testing is the unregulated art of evaluating the invisible against the ambiguous so as to avoid the unthinkable." Unknown
Twitter History
follow me on Twitter
Blog History