Overload resolution is of course the process of taking a bunch of things with the same name and figuring out which of them the user meant. Different languages use different heuristics to try to figure this out. A “heuristic” is just a fancy word for a guess, and I’ve often said that one of the design characteristics of C# is that it is not a “guess what the user meant” kind of language. So if C# is going to make guesses, at least the process by which it does so should be easily explainable to users.

The aspect of overload resolution in C# I want to talk about today is really the fundamental rule by which one potential overload is judged to be better than another for a given call site: closer is always better than farther away. There are a number of ways to characterize “closeness” in C#. Let’s start with the closest and move our way out:

A method first declared in a derived class is closer than a method first declared in a base class.

A method in a nested class is closer than a method in a containing class.

Any method of the receiving type is closer than any extension method.

An extension method found in a class in a nested namespace is closer than an extension method found in a class in an outer namespace.

An extension method found in a class in the current namespace is closer than an extension method found in a class in a namespace mentioned by a using directive.

An extension method found in a class in a namespace mentioned in a using directive where the directive is in a nested namespace is closer than an extension method found in a class in a namespace mentioned in a using directive where the directive is in an outer namespace.

The overload resolution algorithm can be thought of as making a list of every method of a given name, ordering them by closeness using the above metrics, discarding all methods that are farther away than the closest method, and then doing additional tiebreakers on the methods that remain. Of course that is not actually what the compiler does; if for example any instance method can be found then searching for extension methods is elided.

Once you realize that this characterization of “closeness” is the first and deepest cut that the overload resolution algorithm makes, answers to other questions become clear:

And with that, I’m done for 2013. This was an interesting and eventful year for me. New job, new blog location, new office, new product. I’m looking forward to things being a little more routine in 2014. Thanks all for your always-interesting comments and questions. See you for more fabulous adventures next year!