Smarter overload selection #8284
-
I was just putting together a test method for an extension method when I realized that it didn't work conceptually as I imagined. I had the following in my extensions class: public static class MyExtensions
{
public static IServiceCollection AddMyClient(this IServiceCollection serviceCollection, Action<ClientBuilder>? configure = null)
{
if (configure is not null) //if it is, it's ignored
{
//Do something
}
}
public static IServiceCollection AddMyClient(this IServiceCollection serviceCollection, Action<IServiceProvider, ClientBuilder>? configure = null)
{
if (configure is not null) //if it is, it's ignored
{
//Do something
}
}
} In my test application, I did a double take when I saw Visual Studio put a red squiggly under this: builder.Services.AddMyClient(); My theory is that it doesn't know which of the overloads to use here because while they both default to null, the compiler isn't smart enough to know that it doesn't matter which it selects, so it needs the arguments passed (even if they're just discarded), so it knows which to select: builder.Services.AddMyClient(_ => {}); This selects the first overload and assigns the action, so even though it doesn't do anything, it's also not null (so this might take an unexpected path based on the implementation). After reading @HaloFour 's answer below, it clicked for me that of course, there might be something different going in each method so just because it's null, they're still potentially quite different things, so I went back and looked at my implementation. I think the proposal would work well enough (or as I did, just add an overload that doesn't have the Action argument at all, problem solved). While it's a much more complex scenario than originally described (I've updated the code above), fundamentally, it'd still be nice if the compiler were a tad bit smarter - instead of just looking at the method signatures, exclusively when it's ambiguous like this, peek inside the method to see if there's any difference in how that argument is used and if it's used differently between the two. If there is, there's nothing to be done - as we're back in the original scenario. But here, the exact same thing happens - if configure is null, it's ignored, if it is isn't, something happens. So between the two methods, it really doesn't matter which of the two runs because if null, either would yield the same outcome. Updated to better reflect the scenario I was looking at when I first wrote this. |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 9 replies
-
I believe the overload resolution priority proposal will cover this, in that you can specify which of the two methods would be preferred in the case of ambiguity. |
Beta Was this translation helpful? Give feedback.
-
How is the compiler supposed to know which is better? For all it knows, the |
Beta Was this translation helpful? Give feedback.
-
Why would it not matter? You have two different methods. It has to pick one, so you'll get a different program that behaves a different way depending on which it picks. |
Beta Was this translation helpful? Give feedback.
That's not a concept. Precisely for the reason i mentioned above. There is no mechanism to 'peek inside the method'. Consider something as trivial as metadata, and a ref-assembly. There is no 'inside' to know abotu at all. All you have is the signature. That's what defines the contract. The insides are completely unknown and unknowable.