Why does the code below crash the .NET compiler? It was tested on csc.exe version 4.0.
See e.g. here for online demo on different version - it crashes in the same manner while it says dynamic is not supported https://dotnetfiddle.net/FMn59S:
Compilation error (line 0, col 0): Internal Compiler Error (0xc0000005 at address xy): likely culprit is 'TRANSFORM'.
The extension method works fine on List<dynamic>
though.
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>{} }
Update: this doesn't crash the compiler
static void U(Dictionary<string, dynamic> d) { d.M(kvp => Console.WriteLine(kvp)); }
Update 2: the same bug was reported in http://connect.microsoft.com/VisualStudio/feedback/details/892372/compiler-error-with-dynamic-dictinoaries. The bug was reported for FirstOrDefault, but it seems the compiler crashes on any extension method applied to class derived from Dictionary<T1,T2>, where at least one of the parameter types is dynamic
. See an even more general description of the problem below by Erik Funkenbusch.
Update 3: another non-standard behaviour. When I try to call extension method as a static method, that is, F.M(d, kvp => Console.WriteLine(kvp));
, the compiler doesn't crash, but it cannot find the overload: Argument 1: cannot convert from 'C.K' to 'System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<string,dynamic>>'
Update 4 - SOLUTION (kind of): Hans sketched 2nd workaround, which is semantically equivalent to original code, but works only for extension method call and not for standard call. Since the bug is likely caused by the fact that the compiler fails to cast class derived from generic class with multiple parameters (with one being dynamic) to its supertype, the solution is to provide an explicit cast. See https://dotnetfiddle.net/oNvlcL:
((Dictionary<string, dynamic>)d).M(kvp => Console.WriteLine(kvp)); M((Dictionary<string, dynamic>)d, kvp => Console.WriteLine(kvp));
The letter c was applied by French orthographists in the 12th century to represent the sound ts in English, and this sound developed into the simpler sibilant s.
This is a very important rule considering about 25% of words in our language contain a C.] So why do we need a C? When we combine the C with an H we DO make a unique sound. Without a C we would go to Hurch instead of Church, we would listen to a Hime instead of a Chime, etc.
Here's the rule: When 'c' comes directly before the letters 'e', 'i' or 'y' we use the /s/ sound. in other cases we use a /k/ sound.
It is dynamic that is triggering the instability, the crash disappears when you replace it by object.
Which is one workaround, the other is to help it infer the correct T:
static void U(C.K d) { d.M(new Action<KeyValuePair<string, dynamic>>(kvp => Console.WriteLine(kvp))); }
The feedback report that you found is a strong match, no need to file your own I'd say.
Well, the answer to your question as to WHY it crashes the compiler, it's because you've encountered a bug that.... crashes the compiler.
The VS2013 compiler says "Internal Compiler Error (0xc0000005 at address 012DC5B5): likely culprit is 'TRANSFORM'", so clearly it's a bug.
C0000005 is typically a null pointer, or referencing unallocated, or deleted memory. It's a general protection fault.
EDIT:
The problem is also present in pretty much any kind of multiple parameter generic type where the any parameter is dynamic. For instance it crashes on:
List<Tuple<string, dynamic>>{}
It also crashes on
List<KeyValuePair<dynamic, string>>{}
But does not crash on
List<dynamic>{}
but does crash on
List<List<dynamic>>{}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With