2015-01-25 17 views
7

Während ich untersuche, wie C# dynamisches Schlüsselwort funktioniert, stolperte ich über ein seltsames Verhalten. Es sieht fast wie ein Fehler aus, aber wahrscheinlich gibt es einen Grund für das Verhalten.Weird C# dynamisches Verhalten

Im folgenden Code gibt es zwei Aufrufe, einen nach obj1 und einen nach obj2, aber nur einer von ihnen wird korrekt ausgeführt. Es scheint, als wäre der lokale Variablentyp der Grund, aber "Hello" sollte auch von IDynamicTarget aus zugänglich sein, weil es IDynamicTargetBase erweitert.

namespace DynamicTesting 
{ 
    interface IDynamicTargetBase 
    { 
     string Hello(int a); 
    } 

    interface IDynamicTarget : IDynamicTargetBase 
    { 
    } 

    class DynamicTarget : IDynamicTarget 
    { 
     public string Hello(int a) 
     { 
      return "Hello!"; 
     } 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      dynamic a = 123; 

      IDynamicTargetBase obj1 = new DynamicTarget(); 
      obj1.Hello(a); // This works just fine 

      IDynamicTarget obj2 = new DynamicTarget(); 
      obj2.Hello(a); // RuntimeBinderException "No overload for method 'Hello' takes '1' arguments" 
     } 
    } 
} 
+3

scheint auf Mono zu arbeiten: http://ideone.com/PGn3Jp. Hier ist eine Version, die auf .Net Fiddle fehlschlägt: https://dotnetfiddle.net/55ZMAG – Kobi

+2

Das ist ein höllischer Fehler, es seit fünf Jahren zu ignorieren .. –

+0

BTW ist ein niedriger Priorität Bug, weil wenn Argument kompiliert wird Zeit eingegeben, der gleiche Code in dieser Frage wird funktionieren. Ich habe das Gefühl, dass es nur wenige Fälle gibt, in denen Sie ein dynamisches Argument geben ... –

Antwort

0

Es scheint, es ist eine Methode Überladungsauflösung Problem.

Ändern Sie einfach dynamic a = 123 zu int a = 123 und Ihr Code wird funktionieren. Wenn Sie den Methodenaufruf zu obj2.Hello((int)a); ändern. Schließlich geben Sie die Variable als DynamicTarget anstelle von IDynamicTarget und es wird auch funktionieren!

Warum? Wenn Sie mit dynamischen Ausdrücken arbeiten und es mehr als eine Methodenüberladung gibt, deren Aufruf dynamische Argumente hat, kann die Laufzeit nicht auflösen, welche Überladung aufgerufen werden soll, da die Methodenüberladung auf der Art und Reihenfolge der Argumente basiert die so genannte Methode wurde genannt.

Meine Spekulation ist Laufzeitüberlastung Auflösung fehlschlägt, wenn eine Schnittstelle auch andere Schnittstelle implementiert, und die Laufzeit scheint zu verstehen, dass es keine Garantie gibt, dass die zweite Schnittstelle eine Überladung von einer anderen Schnittstellen definieren wird, die auch implementiert, und es zwingt Sie, den eigentlichen Typ des Arguments (der Argumente) während der Kompilierungszeit anzugeben.

[...] aber "Hallo" auch von IDynamicTarget zugänglich sein soll, weil es IDynamicTargetBase erstreckt.

Es ist zugänglich, aber die Laufzeit ist nicht in der Lage zu lösen, wie Argumente Methode der zur Verfügung zu stellen ...