It applies the "better conversion" rules (7.4.3.3 of the C# 3 spec) as part of overload resolution (section 7.4.3 in general).
Basically in this case there's a conversion from string
to object
, but not from object
to string
. Following the rules, that means the conversion from null
to string
is better than the one from null
to object
, so the overload with the string
parameter is used.
Overload resolution can get extremely complicated when the following factors get involved:
- There could be generic methods in the candidate set
- If there are generic methods, type inference is applied to each of them separately, giving different conversion opportunities
- If any arguments are method groups, they could be converted to different delegate types - possibly even using different method signatures if the named method group also has multiple overloads
- Inheritance can lead to surprising results
- Parameter arrays (
params
) add to the fun
- Optional parameters in C# 4 contribute to the decision too
Basically overloading can be a real can of worms - where possible, design overloads so that only one of them will ever be a valid target of any given method call, so that you don't need to worry about the detailed rules.