How does the C# compiler decide which overload to call?
Quick Answer
Overload resolution picks the “best” applicable method: an exact type match beats an implicit conversion; a more specific type beats a less specific one (int over long over object); a non-params form beats the params form; optional-parameter defaults are considered last. If two candidates are equally good, it's a compile error (ambiguous call).
The compiler builds the set of methods with the right name and an argument count that fits, checks that every argument can implicitly convert to the parameter type, and then picks the best match. “Best” roughly means: exact type match beats a conversion, a more derived type beats a base type, and the regular form beats the params form. If nothing is clearly best it's an ambiguous-call error. The classic gotchas are passing null when there are two reference-type overloads, and dynamic, which pushes the whole decision to run time.
- Candidate set: methods with the right name and accessible, with a compatible parameter count (after optionals/params).
- Each argument must be implicitly convertible to the parameter type.
- “Better function member” rules compare candidates pairwise on how well each argument matches.
- Common surprises: passing
nullis ambiguous between two reference-type overloads;0can match an enum overload;dynamicdefers resolution to run time. - Generic methods and extension methods add wrinkles (instance methods win over extensions).