为什么下面的代码会导致.NET编译器崩溃?它已经在版本4.0的csc.exe上进行了测试。
例如,这里有一个在线演示以展示不同版本的情况——它以相同的方式崩溃,同时说动态不受支持: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<T1,T2>类且至少有一个参数类型为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勾画了第二个解决方法,它与原始代码在语义上等价,但仅适用于扩展方法调用而不适用于标准调用。由于该错误可能是由于编译器无法将派生自具有多个参数(其中一个为dynamic)的泛型类的类强制转换为其超类型所致,因此解决方案是提供显式转换。请参见https://dotnetfiddle.net/oNvlcL:
((Dictionary<string, dynamic>)d).M(kvp => Console.WriteLine(kvp));
M((Dictionary<string, dynamic>)d, kvp => Console.WriteLine(kvp));