It depends on TypeA
and TypeB
.
- If exactly one of them is applicable (e.g. there is no conversion from
null
to TypeB
because it's a value type but TypeA
is a reference type) then the call will be made to the applicable one.
- Otherwise it depends on the relationship between
TypeA
and TypeB
.
- If there is an implicit conversion from
TypeA
to TypeB
but no implicit conversion from TypeB
to TypeA
then the overload using TypeA
will be used.
- If there is an implicit conversion from
TypeB
to TypeA
but no implicit conversion from TypeA
to TypeB
then the overload using TypeB
will be used.
- Otherwise, the call is ambiguous and will fail to compile.
See section 7.4.3.4 of the C# 3.0 spec for the detailed rules.
Here's an example of it not being ambiguous. Here TypeB
derives from TypeA
, which means there's an implicit conversion from TypeB
to TypeA
, but not vice versa. Thus the overload using TypeB
is used:
using System;
class TypeA {}
class TypeB : TypeA {}
class Program
{
static void Foo(TypeA x)
{
Console.WriteLine("Foo(TypeA)");
}
static void Foo(TypeB x)
{
Console.WriteLine("Foo(TypeB)");
}
static void Main()
{
Foo(null); // Prints Foo(TypeB)
}
}
In general, even in the face of an otherwise-ambiguous call, to ensure that a particular overload is used, just cast:
Foo((TypeA) null);
or
Foo((TypeB) null);
Note that if this involves inheritance in the declaring classes (i.e. one class is overloading a method declared by its base class) you're into a whole other problem, and you need to cast the target of the method rather than the argument.