Неоднозначный вызов соответствует путанице
Следующий код выдает "неоднозначное совпадение вызова"во время компиляции:
class ABC{}
class DEF{}
class Program
{
static void Main(string[] args)
{
Debug.WriteLine(func(null));
}
static string func(ABC abc)
{
return "";
}
static string func(DEF def)
{
return "";
}
}
Но следующий код компилируется и работает нормально:
static void Main(string[] args)
{
Debug.WriteLine(func(null));
}
static string func(int? abc)
{
return "function a";
}
static string func(float? def)
{
return "function b";
}
Вывод
function a
Как C# узнает, какую функцию выбрать во втором примере?
1 ответ:
Когда компилятор выполняет разрешение перегрузки для вызова функции, подобной этой, он выбирает лучший функциональный членсреди кандидатов, если таковой существует. Определение лучшего функционального члена включает этот отрывок в §7.5.3.2 спецификации языка C#:
7.5.3.2 лучший функциональный член
[...]
Задан список аргументов A с набором выражений аргументов { E1, E2, ..., ЕП } и двумя действующими членами функции МП и MQ с параметром типы { P1, P2, ..., PN } и { Q1, Q2, ..., QN }, MP определяется как лучший функциональный член, чем MQ, если
- для каждого аргумента неявное преобразование из EX в QX является не лучше, чем неявное преобразование из EX в PX, и
- по крайней мере для одного аргумента преобразование из EX в PX является лучше, чем преобразование из EX в QX.
[...]
В этом случае
MP
является первым методом (P1
будучиint?
) иMQ
является вторым методом (Q1
будучиfloat?
). Таким образом, поведение легко объяснимо, если мы можем доказать, что преобразование изnull
вint?
является лучше, чем преобразование вfloat?
.Это определяется правилами в §7.5.3.5:
7.5.3.5 лучшая цель преобразования
Учитывая два различных типа T1 и T2, T1 является лучшей целью преобразования чем T2, если выполняется хотя бы одно из следующих условий:
- неявное преобразование из T1 в T2 существует, и никакого неявного преобразования из T2 в T1 не существует
Поскольку неявное преобразование из
int
вfloat
существует, но одно изfloat
вint
не имеет (ссылки),int
является ли лучшей целью преобразования при выборе между двумя типами.В вашем примере мы имеем дело с обнуляемыми версиями этих типов, но та же логика применима из-за
[14]}6.1.4 неявное обнуление преобразованияПредопределенные неявные преобразования, которые работают с ненулевым значением типы также могут использоваться с формами, допускающими обнуление этих типов.