Here’s a pattern that I’ve seen occur a number of times - a pair of method overloads, one accepting IEnumerable<T> and the other accepting params T[].

void Process(IEnumerable<string> commandline) { ... }
void Process(params string[] parameters) { ... }

Often, the params edition is provided as a convenience overload, making the API simpler for consumers. The implementation is usually a simple delegation call to the main method:

void Process(params string[] parameters)
{
    Process(parameters);
}

There’s a trap here though - as shown, you’ll get a Stack Overflow exception thrown in good order.

The reason is simple - but perhaps not obvious. When the compiler is matching method signatures to work out which version of Process() to invoke, there’s a better match with string[] than with IEnumerable<string>, so the generated code goes into a tight loop.

The solution is to cast parameters to the more general type so that there is only one viable match:

void Process(params string[] parameters)
{
    Process( (IEnumerable<string>) parameters );
}

The way that the compiler selects which overload to call is entirely predictable, but complex, and sometimes gives unexpected results. It’s worth learning enough about the process to be able to troubleshoot problems (like this one). That said, if your specific problem is too complex, the best answer might be to rename some of the overloads so that a future maintainer doesn’t have the same problem to face.

Comments

blog comments powered by Disqus
Next Post
Doing less with LINQ  30 Jun 2010
Prior Post
NAntGraph v2.2 Released  16 Jun 2010
Related Posts
Using Constructors  27 Feb 2023
An Inconvenient API  18 Feb 2023
Method Archetypes  11 Sep 2022
A bash puzzle, solved  02 Jul 2022
A bash puzzle  25 Jun 2022
Improve your troubleshooting by aggregating errors  11 Jun 2022
Improve your troubleshooting by wrapping errors  28 May 2022
Keep your promises  14 May 2022
When are you done?  18 Apr 2022
Fixing GitHub Authentication  28 Nov 2021
Archives
June 2010
2010