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

Fra*_*nta 26 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>{}
}
Run Code Online (Sandbox Code Playgroud)

更新:这不会使编译器崩溃

static void U(Dictionary<string, dynamic> d)
{
    d.M(kvp => Console.WriteLine(kvp));
}
Run Code Online (Sandbox Code Playgroud)

更新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));
Run Code Online (Sandbox Code Playgroud)

Han*_*ant 18

它是动态的,触发不稳定性,当你用对象替换它时,崩溃就会消失.

这是一种解决方法,另一种是帮助它推断出正确的T:

static void U(C.K d) {
    d.M(new Action<KeyValuePair<string, dynamic>>(kvp => Console.WriteLine(kvp)));
}
Run Code Online (Sandbox Code Playgroud)

您找到的反馈报告是一个强有力的匹配,不需要提交您自己的说法.

  • C#编译器在这段代码中有一个难以解决的问题,双类型推断结合*dynamic*是可替换的,因为Dictionary实现协变接口会爆炸它必须考虑的可能匹配的数量.我不想自己写代码,不可能完全测试.底层崩溃只是一个NullReferenceException,每天都在C#程序中发生,它只是在C++中发生时看起来很丑陋.Microsoft工程师需要完全诊断它.简化它必须完成的工作,崩溃消失. (4认同)

Eri*_*sch 15

好吧,关于为什么它会崩溃编译器的问题的答案,这是因为你遇到了一个错误......崩溃了编译器.

VS2013编译器说"内部编译器错误(地址012DC5B5处的0xc0000005):可能的罪魁祸首是'TRANSFORM'",所以很明显这是一个错误.

C0000005通常是空指针,或引用未分配或已删除的内存.这是一般性保护错误.

编辑:

问题也存在于几乎任何类型的多参数泛型类型中,其中any参数是动态的.例如它崩溃了:

List<Tuple<string, dynamic>>{}
Run Code Online (Sandbox Code Playgroud)

它也崩溃了

List<KeyValuePair<dynamic, string>>{}
Run Code Online (Sandbox Code Playgroud)

但不会崩溃

List<dynamic>{}
Run Code Online (Sandbox Code Playgroud)

但确实崩溃了

List<List<dynamic>>{}
Run Code Online (Sandbox Code Playgroud)

  • @HenkHolterman - 首先,当我回答这个问题时,问题没有包含相同的信息.他补充说,之后.第二,答案是第一句,清楚地写着"你问题的答案".我知道这听起来很愚蠢,但这就是答案.问一个愚蠢的问题,你得到一个愚蠢的答案.我们没有编译器的源代码,所以我们无法知道其他的东西. (9认同)
  • 那么......这是问题的重复吗?答案部分在哪里? (7认同)
  • 您可能希望将此信息添加到问题中,但它并没有真正回答它. (3认同)