Ответ 1
Хорошая добыча Тимви.
Наша поддержка динамических групп методов слаба. Например, рассмотрим этот более простой случай:
class C
{
public void M() {}
}
class P
{
static void Main()
{
dynamic d = new C();
C c = new C();
Action a1 = c.M; // works
Action a2 = d.M; // fails at runtime
d.M
интерпретируется как свойство get (или доступ к полю) динамической исполняемой средой, и когда он разрешается как группа методов, он не работает во время выполнения.
То же самое происходит и в вашем случае, это просто немного неясно. Когда вы говорите MyDelegate x = new MyDelegate(someOtherDelegate);
, который обрабатывается компилятором так же, как если бы вы сказали MyDelegate x = someOtherDelegate.Invoke;
. Динамическая часть выполнения не знает, чтобы сделать это преобразование, и даже если бы это произошло, она не смогла обработать решение группы методов, которая является результатом части .Invoke
выражения.
Есть ли что-либо в спецификации С#, которая допускает это поведение, или это ошибка в компиляторе Microsoft С#?
В спецификации не указано, что это должна быть ошибка времени выполнения, и подразумевает, что она должна корректно обрабатываться во время выполнения; ясно, что реализация этого не делает. Хотя это и является недостатком реализации, я бы не назвал это "ошибкой", потому что мы сознательно сделали поведение, которое вы обнаружили. У нас не было ресурсов, чтобы эти виды выражений работали правильно, поэтому мы оставили их в качестве ошибок. Если мы когда-либо получим хороший способ представления групп методов в динамической среде выполнения, мы можем ее реализовать.
Аналогичным образом в динамическом коде невозможно представить понятие "эта динамическая вещь - это лямбда-выражение, где типы параметров должны определяться во время выполнения". Если у нас будет хороший способ представить их в будущем, мы можем выполнить эту работу.
Сэм рассказал об этом еще в 2008 году; см. его статью:
http://blogs.msdn.com/b/samng/archive/2008/11/02/dynamic-in-c-ii-basics.aspx