为什么C#编译器会在此代码上崩溃?

时间:2014-06-21 19:40:25

标签: c# csc

为什么下面的代码会破坏.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));

2 个答案:

答案 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>>{}