为什么c#编译器在这段代码上崩溃了?
本文关键字:代码 崩溃 编译器 段代码 为什么 | 更新日期: 2023-09-27 18:09:36
为什么下面的代码会使。net编译器崩溃?在csc.exe 4.0版本上进行了测试。
参见这里不同版本的在线演示-它以同样的方式崩溃,同时它说不支持动态https://dotnetfiddle.net/FMn59S:
编译错误(第0行,col 0):内部编译错误(0xc0000005 at address 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的,但似乎编译器在应用于从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概述了第二个解决方案,它在语义上等同于原始代码,但只适用于扩展方法调用,而不适用于标准调用。由于该错误可能是由于编译器未能将具有多个参数(其中一个是动态的)的泛型类派生的类强制转换为其超类型而引起的,因此解决方案是提供显式强制转换。见https://dotnetfiddle.net/oNvlcL:
((Dictionary<string, dynamic>)d).M(kvp => Console.WriteLine(kvp));
M((Dictionary<string, dynamic>)d, kvp => Console.WriteLine(kvp));
是动态触发不稳定性,当你用对象替换它时崩溃消失。
这是一个解决方法,另一个是帮助它推断正确的T:
static void U(C.K d) {
d.M(new Action<KeyValuePair<string, dynamic>>(kvp => Console.WriteLine(kvp)));
}
你找到的反馈报告是一个强有力的匹配,我认为没有必要提交你自己的。
好吧,你的问题的答案,为什么它崩溃编译器,这是因为你遇到了一个bug ....编译器崩溃。
VS2013编译器说"内部编译器错误(0xc0000005在地址012DC5B5):可能的罪魁祸首是'TRANSFORM'",所以很明显这是一个错误。
C0000005通常是一个空指针,或引用未分配或已删除的内存。这是一般的保护故障。
编辑:这个问题也存在于几乎任何类型的多参数泛型类型中,其中任意参数是动态的。例如:
List<Tuple<string, dynamic>>{}
也会在
上崩溃List<KeyValuePair<dynamic, string>>{}
但不崩溃
List<dynamic>{}
但是在
上崩溃List<List<dynamic>>{}