Почему вы не можете использовать функцию anon с динамическим параметром?

Просто наткнулся на это сегодня

Анонимная функция или группа методов не могут использоваться в качестве составной части значение динамически связанной операции.

при попытке сделать

static R ifNotNull<R>(dynamic o, Func<dynamic, R> returnFunc, R otherwise) {
    return ReferenceEquals(null, o) ? otherwise : returnFunc(o);
}

и используйте его с

dynamic firstAddress = ...;
return ifNotNull<string>(firstAddress, (a) => a.address_1, null)

Теперь большинство ограничений по динамике имеют смысл для меня - вы не можете использовать метод расширения, потому что как компилятор должен решить, какой статикой он должен скомпилировать? Но я этого не понимаю. Откуда возникает путаница? Что такое ограничение?

Ответы

Ответ 1

Каков статический тип lamba a => a.address_1? У вас может возникнуть соблазн сказать это Func<dynamic, dynamic>. Но помните:

Лямбда-выражение представляет собой анонимную функцию, которую вы можете использовать для создавать делегаты или типы дерева выражений.

Так что, возможно, это Expression<Func<dynamic, dynamic>>. Самма сама по себе не имеет единого статического типа.

Теперь обычно вводится вывод, что вы передаете lamba функции, которая принимает Func, и она будет преобразована в делегат во время компиляции. Однако при вызове с динамическими аргументами вызов метода отправляется динамически.

Если у вас есть вызов метода с динамическим аргументом, он отправляется динамически, период. Во время привязки времени выполнения все статические типы ваших аргументов известны (выделение мое), и типы выбираются для динамического аргументы, основанные на их фактических значениях.

Таким образом, тот факт, что ваш метод принимает Func, не учитывается, поскольку фактический вызов метода не определяется до времени выполнения, поэтому нет тип вывода.

Чтобы получить это для компиляции, вам нужно отдать свой lamba на Func<dynamic, string>, как показано ниже:

return ifNotNull<string>(firstAddress, new Func<dynamic, string>((a) => a.address_1), null);

Теперь известен статический тип вашей ламы.

Ответ 2

Я имел в виду, что вам нужно применить метод lambda к ожидаемому выражению. Тогда все будет хорошо.

Вот так:

return ifNotNull(firstAddress, (Func<dynamic, string>)((a) => a.address_1), null);