Overloaded Method Resolution

  • Thread starter Thread starter Hamza GOLYERI
  • Start date Start date
H

Hamza GOLYERI

Hi,

I even read the related parts of language specification
but could not find anything that explains the following:
====================
public class A {
public void Foo(object o) {
System.Console.WriteLine("Foo(object o)");
}

public void Foo(string s) {
System.Console.WriteLine("Foo(string s)");
}

public static void Main() {
A a = new A();
a.Foo(null);
}
}
===================
I expect to get ("Foo(object o)" but this prints ("Foo
(string s)"). Can anybody explain why? Which part of the
language specification explains this behavior?

Thanks,
Hamza GOLYERI
 
Interestig. It appears that null is defined as a string. Perhaps
strange, but then again, it's not really an object either, and not really
a string (confused).
 
Morten Wennevik said:
Interestig. It appears that null is defined as a string. Perhaps
strange, but then again, it's not really an object either, and not really
a string (confused).

No, the null literal is a value of the null type, which can be
implicitly converted to any reference type.
 
Hamza GOLYERI said:
I even read the related parts of language specification
but could not find anything that explains the following:
====================
public class A {
public void Foo(object o) {
System.Console.WriteLine("Foo(object o)");
}

public void Foo(string s) {
System.Console.WriteLine("Foo(string s)");
}

public static void Main() {
A a = new A();
a.Foo(null);
}
}
===================
I expect to get ("Foo(object o)" but this prints ("Foo
(string s)"). Can anybody explain why? Which part of the
language specification explains this behavior?

null can be implicitly converted to both string and object, so both
methods are candidates. Then from section 14.4.2 (ECMA numbering):

<quote>
Otherwise, the best function member is the one function member that is
better than all other function members with respect to the given
argument list, provided that each function member is compared to all
other function members using the rules in §14.4.2.2
</quote>

Now 14.4.2.2 says:

<quote>
Given an argument list A with a set of argument types A1, A2, ..., AN
and two applicable function members MP and MQ with parameter types P1,
P2, ..., PN and Q1, Q2, ..., QN, MP is defined to be a better function
member than MQ if

* for each argument, the implicit conversion from AX to PX is not
worse than the implicit conversion from AX to QX, and
* for at least one argument, the conversion from AX to PX is better
than the conversion from AX to QX.
</quote>

So, we've only got one argument here, so the two conversions in
question are from null to object and from null to string. Looking at
14.4.2.3, we have:

<quote>
Given an implicit conversion C1 that converts from a type S to a type
T1, and an implicit conversion C2 that converts from a type S to a type
T2, the better conversion of the two conversions is determined as
follows:

If T1 and T2 are the same type, neither conversion is better.
If S is T1, C1 is the better conversion.
If S is T2, C2 is the better conversion.
If an implicit conversion from T1 to T2 exists, and no implicit
conversion from T2 to T1 exists, C1 is the better conversion.
If an implicit conversion from T2 to T1 exists, and no implicit
conversion from T1 to T2 exists, C2 is the better conversion.
</quote>

Here S is the null type, T1 is object and T2 is string. (The rules are
symmetric, so you could choose them the other way round if you wanted.)

string and object aren't the same type, so the first rule doesn't
apply.

null isn't the same type as either string or object, so the second and
third rules don't apply.

There is no implicit conversion from object to string, so the fourth
rule doesn't apply.

There is an implicit conversion from string to object, but not vice
versa, so the fifth rule *does* apply, and the conversion from null to
string is better than the conversion from null to object - hence the
method which is chosen.
 
Great explanation! In summary since string is a "closer" conversion than
the base level Object it is picked by the runtime.

--
Eric Newton
C#/ASP Application Developer
(e-mail address removed)-software.com [remove the first "CC."]

Hamza GOLYERI said:
I even read the related parts of language specification
but could not find anything that explains the following:
====================
public class A {
public void Foo(object o) {
System.Console.WriteLine("Foo(object o)");
}

public void Foo(string s) {
System.Console.WriteLine("Foo(string s)");
}

public static void Main() {
A a = new A();
a.Foo(null);
}
}
===================
I expect to get ("Foo(object o)" but this prints ("Foo
(string s)"). Can anybody explain why? Which part of the
language specification explains this behavior?

null can be implicitly converted to both string and object, so both
methods are candidates. Then from section 14.4.2 (ECMA numbering):

<quote>
Otherwise, the best function member is the one function member that is
better than all other function members with respect to the given
argument list, provided that each function member is compared to all
other function members using the rules in §14.4.2.2
</quote>

Now 14.4.2.2 says:

<quote>
Given an argument list A with a set of argument types A1, A2, ..., AN
and two applicable function members MP and MQ with parameter types P1,
P2, ..., PN and Q1, Q2, ..., QN, MP is defined to be a better function
member than MQ if

* for each argument, the implicit conversion from AX to PX is not
worse than the implicit conversion from AX to QX, and
* for at least one argument, the conversion from AX to PX is better
than the conversion from AX to QX.
</quote>

So, we've only got one argument here, so the two conversions in
question are from null to object and from null to string. Looking at
14.4.2.3, we have:

<quote>
Given an implicit conversion C1 that converts from a type S to a type
T1, and an implicit conversion C2 that converts from a type S to a type
T2, the better conversion of the two conversions is determined as
follows:

If T1 and T2 are the same type, neither conversion is better.
If S is T1, C1 is the better conversion.
If S is T2, C2 is the better conversion.
If an implicit conversion from T1 to T2 exists, and no implicit
conversion from T2 to T1 exists, C1 is the better conversion.
If an implicit conversion from T2 to T1 exists, and no implicit
conversion from T1 to T2 exists, C2 is the better conversion.
</quote>

Here S is the null type, T1 is object and T2 is string. (The rules are
symmetric, so you could choose them the other way round if you wanted.)

string and object aren't the same type, so the first rule doesn't
apply.

null isn't the same type as either string or object, so the second and
third rules don't apply.

There is no implicit conversion from object to string, so the fourth
rule doesn't apply.

There is an implicit conversion from string to object, but not vice
versa, so the fifth rule *does* apply, and the conversion from null to
string is better than the conversion from null to object - hence the
method which is chosen.
 
Back
Top