为什么下面的代码会破坏.NET编译器?它在csc.exe 4.0版上进行了测试。
参见例如这里是针对不同版本的在线演示 - 它以相同的方式崩溃,同时表示不支持动态https://dotnetfiddle.net/FMn59S:
编译错误(第0行,第0列):内部编译器错误(地址xy处为0xc0000005):可能的罪魁祸首是“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报告了该错误,但似乎编译器在应用于从Dictionary&lt; T1,T2&gt;派生的类的任何扩展方法上崩溃,其中至少一个参数类型是dynamic
。请参阅Erik Funkenbusch对此问题的更一般描述。
更新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 - 解决方案(种类):Hans草拟了第二种解决方法,它在语义上等同于原始代码,但仅适用于扩展方法调用而不适用于标准调用。由于该错误可能是由于编译器无法将具有多个参数(其中一个是动态的)的泛型类派生的类转换为其超类型,因此解决方案是提供显式强制转换。见https://dotnetfiddle.net/oNvlcL:
((Dictionary<string, dynamic>)d).M(kvp => Console.WriteLine(kvp));
M((Dictionary<string, dynamic>)d, kvp => Console.WriteLine(kvp));
答案 0 :(得分:18)
动态触发了不稳定性,当您用 object 替换它时崩溃消失。
这是一种解决方法,另一种是帮助它推断出正确的T:
static void U(C.K d) {
d.M(new Action<KeyValuePair<string, dynamic>>(kvp => Console.WriteLine(kvp)));
}
你找到的feedback report是一个很强的匹配,不需要提交你自己的,我会说。
答案 1 :(得分:15)
好吧,关于为什么它会使编译器崩溃的问题的答案,因为你遇到了一个错误......导致编译器崩溃。
VS2013编译器说&#34;内部编译错误(地址012DC5B5为0xc0000005):可能的罪魁祸首是&#39; TRANSFORM&#39;&#34;&#34;&#34;&#39;&#39;&#39;&#39;&#39;&#39;&#39;&#39;&#39;&#39;&#39;&#39;&#39;&#39;
C0000005通常是空指针,或引用未分配或已删除的内存。这是一般性保护错误。
编辑:
问题也存在于几乎任何类型的多参数泛型类型中,其中any参数是动态的。例如,它崩溃了:
List<Tuple<string, dynamic>>{}
它也崩溃了
List<KeyValuePair<dynamic, string>>{}
但不会崩溃
List<dynamic>{}
但确实崩溃了
List<List<dynamic>>{}