27 votes

Pourquoi le compilateur C# se plante-t-il sur ce code ?

Pourquoi le code ci-dessous fait-il planter le compilateur .NET ? Il a été testé sur csc.exe version 4.0.

Voir par exemple ici pour une démo en ligne sur une version différente - elle se bloque de la même manière alors qu'il est indiqué que la dynamique n'est pas prise en charge. https://dotnetfiddle.net/FMn59S :

Erreur de compilation (ligne 0, col 0) : Internal Compiler Error (0xc0000005 at address xy) : le coupable probable est 'TRANSFORM'.

La méthode d'extension fonctionne bien sur List<dynamic> cependant.

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

Mise à jour : cela ne fait pas planter le compilateur

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

Mise à jour 2 : le même bogue a été signalé dans http://connect.microsoft.com/VisualStudio/feedback/details/892372/compiler-error-with-dynamic-dictinoaries . Le bogue a été signalé pour FirstOrDefault, mais il semble que le compilateur se plante sur toute méthode d'extension appliquée à une classe dérivée de Dictionary<T1,T2>, où au moins un des types de paramètres est dynamic . Voir ci-dessous une description encore plus générale du problème par Erik Funkenbusch.

Mise à jour 3 : un autre comportement non standard. Lorsque j'essaie d'appeler une méthode d'extension comme une méthode statique, c'est-à-dire, F.M(d, kvp => Console.WriteLine(kvp)); le compilateur ne se plante pas, mais il ne trouve pas la surcharge : Argument 1: cannot convert from 'C.K' to 'System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<string,dynamic>>'

Mise à jour 4 - SOLUTION (en quelque sorte) : Hans a esquissé une 2ème solution de contournement, qui est sémantiquement équivalente au code original, mais ne fonctionne que pour l'appel de la méthode d'extension et non pour l'appel standard. Puisque le bogue est probablement causé par le fait que le compilateur n'arrive pas à caster une classe dérivée d'une classe générique avec plusieurs paramètres (dont l'un est dynamique) vers son supertype, la solution est de fournir un cast explicite. Voir https://dotnetfiddle.net/oNvlcL :

((Dictionary<string, dynamic>)d).M(kvp => Console.WriteLine(kvp));
M((Dictionary<string, dynamic>)d, kvp => Console.WriteLine(kvp));

18voto

Hans Passant Points 475940

Il est dynamique qui déclenche l'instabilité, le crash disparaît lorsque vous le remplacez par objet .

C'est une solution de rechange, l'autre consiste à l'aider à déduire le T correct :

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

El rapport de rétroaction que vous avez trouvé correspond bien, pas besoin de déposer le vôtre je dirais.

15voto

Erik Funkenbusch Points 53436

Eh bien, la réponse à votre question de savoir POURQUOI il fait planter le compilateur, c'est parce que vous avez rencontré un bug qui.... fait planter le compilateur.

Le compilateur VS2013 indique "Internal Compiler Error (0xc0000005 at address 012DC5B5) : likely culprit is 'TRANSFORM'", donc il s'agit clairement d'un bug.

C0000005 est généralement un pointeur nul, ou une référence à de la mémoire non allouée ou supprimée. C'est un défaut de protection général.

EDIT :

Le problème est également présent dans presque tous les types génériques à paramètres multiples où le paramètre quelconque est dynamique. Par exemple, il se bloque sur :

List<Tuple<string, dynamic>>{}

Il se bloque également sur

List<KeyValuePair<dynamic, string>>{}

Mais ne se plante pas sur

List<dynamic>{}

mais se bloque sur

List<List<dynamic>>{}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X