2015-07-30 1 views
14

Просто столкнулся с этим сегодняПочему вы не можете использовать функцию 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) 

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

+2

Там, вероятно, проблема с компиляции '(а) => a.address_1' в' returnFunc'.В ожидании Эрика Липперта ответить на этот вопрос :-) – dasblinkenlight

+0

Кстати, в чем разница между вашим кодом и 'static R ifNotNull (object o, Func returnFunc, R в противном случае) {...}'? – dasblinkenlight

+0

@dasblinkenlight именно то, о чем я думал. Подготовьтесь к Lippert в 3..2..1 ... –

ответ

11

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

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

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

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

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

Поэтому тот факт, что ваш метод принимает Func не принимать во внимание, так как the actual method call isn't determined until runtime так нет вывода типа.

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

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

Теперь статический тип вашего LAMDA известен.

+0

Спасибо за солидный ответ. В этом есть смысл. Хотя я все еще немного подшутил, я не получил ответа от липперта ... –

1

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

Как это:

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

 Смежные вопросы

  • Нет связанных вопросов^_^