Подтвердить что ты не робот

Нулевая динамическая переменная и функция перегрузки

Пример кода:

private void DoSomething(object obj)
{
    MessageBox.Show("called object");
}

private void DoSomething(params object[] obj)
{
    MessageBox.Show("called object[]");
}


private void button1_Click(object sender, EventArgs e)
{
    decimal? amount = null;
    dynamic obj = amount;

    DoSomething(obj); 
}

При нажатии кнопки 1 отображается сообщение "вызываемый объект []". Кажется, что перегруженный метод с параметром object [] является предпочтительным в этом примере. Любые идеи почему? Мне просто любопытно больше всего.

(Предыстория: это поведение вызвало некоторые неожиданные результаты в Razor с динамическими представлениями Форматирование десятичной дроби в RazorEngine.

4b9b3361

Ответ 1

Это потому, что вы можете отбрасывать object[] до object, а не наоборот. object[] более конкретна и, следовательно, предпочтительна в разрешении метода.

7.5.3.2 Более эффективный член функции

(...)

Учитывая список аргументов A с набором выражений аргументов { E1, E2, ..., EN } и двумя применимыми членами функции MP и MQ с типами параметров { P1, P2, ..., PN } и { Q1, Q2, ..., QN }, MP определяется как лучшая функция член, чем MQ, если

  • для каждого аргумента, неявное преобразование из EX в QX не лучше, чем неявное преобразование от EX до PX и
  • для хотя бы одного аргумента, преобразование из EX в PX лучше, чем преобразование из EX в QX.

И позже определяется лучшая цель преобразования:

7.5.3.5 Лучшая цель преобразования

Учитывая два разных типа T1 и T2, T1 является лучшей целью преобразования, чем T2, если выполняется хотя бы одно из следующих значений:

  • Неявное преобразование из T1 в T2 существует, а неявное преобразование из T2 в T1 существует

(...)

В вашем примере T1 есть object[] и T2 is object.

Ответ 2

Проблема не связана с "нулевой динамической переменной". Даже если вы вызываете DoSomething(null), предпочтительной будет перегрузка object[].

Это связано с тем, что хотя null может быть либо object, либо object[], последний предпочтительнее из-за того, что он является лучшей целью конверсии, как объясняется MarcinJuraszek.

Однако, если вы явно укажете тип:

object x = null;
DoSomething(x);

Затем будет вызываться перегрузка object, поскольку компилятор уже знает тип нулевой переменной.