2010-02-21 4 views
49

Il y a un comportement étrange avec l'utilisation dynamique C# 4.0:Quelque chose ne va pas avec le mot-clé dynamique dans C# 4.0?

using System; 

class Program { 
    public void Baz() { Console.WriteLine("Baz1"); } 
    static void CallBaz(dynamic x) { x.Baz(); } 

    static void Main(string[] args) { 
    dynamic a = new Program(); 
    dynamic b = new { Baz = new Action(() => Console.WriteLine("Baz2")) }; 

    CallBaz(a); // ok 
    CallBaz(b); // ok 
    CallBaz(a); // Unhandled Exception: 
    // Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 
    // The name 'Baz' is bound to a method and cannot be used like a property 
    } 
} 

J'utilise Visual Studio 2010 Release Candidate.

Est-ce un bug? Si c'est vrai, cela sera-t-il corrigé dans la version?

+6

Où est Eric Lippert: D –

+1

Je peux le reproduire aussi ... Le premier appel à CallBaz (a) fonctionne bien, le second appel échoue. Cela ressemble à un bug en effet, et un sérieux ... –

+2

Intéressant.J'ai envoyé un e-mail dans une liste appropriée - j'espère que cela attirera bientôt l'attention. –

Répondre

32

Je peux confirmer que c'est effectivement un bug. La description rapide de ce qui ne va pas ici est la suivante: Dans CallBaz, il y a un seul appel appelé trois fois. Cet appel est un InvokeMember, car c'est la meilleure estimation que le compilateur peut faire avec la syntaxe C#, bien qu'il puisse, en réalité, se résoudre en un GetMember suivi d'un Invoke. Pendant la deuxième exécution du callsite, c'est bien la liaison que l'exécution trouve. Et donc il produit un report à un GetMember suivi d'une invocation. Le bogue est que ce report ne se limite pas correctement au cas où l'argument est le type anonyme. Par conséquent, dans la troisième exécution, le report intervient et le GetMember tente de se lier au programme, ce qui échoue bien sûr.

Merci d'avoir trouvé cet article. Comme Eric le fait remarquer, nous sommes à un stade très avancé ici, et il devient difficile de régler les problèmes avant d'expédier. Mais nous voulons également expédier le bon produit. Je vais faire ce que je peux pour résoudre ce problème, même si je ne peux pas réussir. Si vous trouvez quelque chose d'autre, n'hésitez pas à me contacter. =)

MISE À JOUR:

Bien que je ne peux pas garantir ce que la version finale de VS 2010 et C# 4 ressemblera quand il est livré, je peux dire que j'ai réussi à pousser ce correctif à travers. La version d'escrow de la version d'aujourd'hui se comporte correctement pour votre code. Sauf catastrophe, vous verrez cela fixé à la libération. Merci encore. Je te dois une bière.

+2

Bien, merci, Chris! – ControlFlow

+0

Wow, c'était rapide ... bien fait, c'est une très bonne nouvelle! –

2

Même chose se produit pour moi, je vous suggère de le signaler here.

8

Cela ressemble à un bug sérieux ...

Notez que cela fonctionne très bien si vous utilisez un ExpandoObject au lieu d'un type anonyme:

using System; 
using System.Dynamic; 

class Program { 
    public void Baz() { Console.WriteLine("Baz1"); } 
    static void CallBaz(dynamic x) { x.Baz(); } 

    static void Main(string[] args) { 
    dynamic a = new Program(); 
    dynamic b = new ExpandoObject(); 
    b.Baz = new Action(() => Console.WriteLine("Baz2")); 

    CallBaz(a); // ok 
    CallBaz(b); // ok 
    CallBaz(a); // ok 
    } 
} 

Donc, la question semble spécifique à des objets anonymes ..

Apparemment, dans le deuxième appel à CallBaz(a), le DLR tente toujours d'accéder à Baz en tant que propriété, car il s'agissait d'une propriété du type anonyme. Je soupçonne que le classeur C# fait une mise en cache de la résolution d'appel pour de meilleures performances, mais dans ce cas, il est clairement cassé ...

+1

Oui, je le pense aussi, c'est un problème de cache ... – ControlFlow

11

Apparence suspecte. Je vais l'envoyer à l'essai et nous verrons ce qu'ils disent. Juste pour définir les attentes: s'il s'agit d'un bug, et qu'il n'a pas été trouvé et corrigé, les chances sont bonnes qu'un correctif ne soit pas inclus dans la version finale.

Merci d'avoir porté cela à notre attention!

Questions connexes