Нулевая динамическая переменная и функция перегрузки
Пример кода:
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.
Ответы
Ответ 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
, поскольку компилятор уже знает тип нулевой переменной.