Почему код ниже разбивает компилятор .NET? Он был протестирован на csc.exe версии 4.0.
См. здесь для онлайн-демонстрации в другой версии - он падает таким же образом, пока он говорит, что динамический не поддерживается https://dotnetfiddle.net/FMn59S:
Ошибка компиляции (строка 0, col 0): Внутренняя ошибка компилятора (0xc0000005 по адресу xy): вероятным виновником является "TRANSFORM".
Метод расширения отлично работает на List<dynamic>
.
using System;
using System.Collections.Generic;
static class F {
public static void M<T>(this IEnumerable<T> enumeration, Action<T> action){}
static void U(C.K d) {
d.M(kvp => Console.WriteLine(kvp));
}
}
class C {
public class K : Dictionary<string, dynamic>{}
}
Обновление: это не сбой компилятора
static void U(Dictionary<string, dynamic> d)
{
d.M(kvp => Console.WriteLine(kvp));
}
Обновление 2: эта ошибка была отмечена в http://connect.microsoft.com/VisualStudio/feedback/details/892372/compiler-error-with-dynamic-dictinoaries. Об ошибке сообщалось для FirstOrDefault, но, похоже, компилятор сбой на любом методе расширения, применяемом к классу, полученному из словаря < T1, T2 > , где по крайней мере один из типов параметров имеет значение dynamic
. См. Еще более общее описание проблемы, приведенной ниже Эриком Функенбушем.
Обновление 3: другое нестандартное поведение. Когда я пытаюсь вызвать метод расширения как статический метод, то есть F.M(d, kvp => Console.WriteLine(kvp));
, компилятор не сбой, но он не может найти перегрузку:
Argument 1: cannot convert from 'C.K' to 'System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<string,dynamic>>'
Обновление 4 - РЕШЕНИЕ (вид): Ганс набросал второе обходное решение, которое семантически эквивалентно исходному коду, но работает только для вызова метода расширения, а не для стандартного вызова. Поскольку ошибка, скорее всего, вызвана тем фактом, что компилятор не может использовать класс, полученный из универсального класса, с несколькими параметрами (с одним из которых является динамическим) до своего супертипа, решение заключается в предоставлении явного приведения. См. https://dotnetfiddle.net/oNvlcL:
((Dictionary<string, dynamic>)d).M(kvp => Console.WriteLine(kvp));
M((Dictionary<string, dynamic>)d, kvp => Console.WriteLine(kvp));