Это зависит от TypeA
и TypeB
.
- Если только один из них применим (например, не существует переход от
null
к TypeB
, потому что это тип значения, но TypeA
является ссылочным типом), то вызов будет выполнен к соответствующему одному.
- В противном случае это зависит от отношений между
TypeA
и TypeB
.
- Если существует неявное преобразование из
TypeA
в TypeB
, но не неявное преобразование из TypeB
в TypeA
будет использоваться перегрузка с помощью TypeA
.
- Если существует неявное преобразование из
TypeB
в TypeA
, но не неявное преобразование из TypeA
в TypeB
будет использоваться перегрузка с помощью TypeB
.
- В противном случае вызов неоднозначен и не будет скомпилирован.
можно найти в разделе 7.4.3.4 в спецификации C# 3.0 для подробных правил.
Вот пример того, что это не двусмысленно. Здесь TypeB
происходит от TypeA
, что означает неявное преобразование от TypeB
до TypeA
, но не наоборот. При этом используется перегрузка с помощью TypeB
:
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)
}
}
В общем, даже перед лицом иначе-неоднозначного вызова, чтобы гарантировать, что используется определенная перегрузка, просто привести:
Foo((TypeA) null);
или
Foo((TypeB) null);
Обратите внимание, что если это включает наследование в объявляющих классах (т.е. один класс перегружает метод, объявленный его базовым классом), вы сталкиваетесь с целым рядом проблем, и вам нужно чтобы отличить цель метода, а не аргумент.
Еще один, чтобы быть в курсе перегружен методы, где по крайней мере один метод использует Params ключевое слово. –