2015-01-25 41 views
7

Durante l'analisi di come funziona la parola chiave dinamica C#, sono incappato in qualche comportamento strano. Sembra quasi un bug, ma probabilmente è più probabile che ci sia una ragione per il comportamento.Comportamento dinamico C# strano

Nel codice sottostante, ci sono due chiamate, una per obj1 e una per obj2, ma solo una di esse viene eseguita correttamente. Sembra che il tipo di variabile locale sia la ragione, ma "Hello" dovrebbe essere accessibile anche da IDynamicTarget, perché estende IDynamicTargetBase.

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

sembra funzionare su Mono: http://ideone.com/PGn3Jp. Ecco una versione che fallisce. Net Fiddle: https://dotnetfiddle.net/55ZMAG – Kobi

+2

Questo è un bizzarro bug da ignorare per cinque anni. –

+0

BTW è un bug a bassa priorità perché se l'argomento è compilato- tempo digitato, lo stesso codice in questa domanda funzionerà. Sento che ci sono pochi casi in cui si dà un argomento dinamico ... –

risposta

0

Sembra che si tratti di un problema di risoluzione del sovraccarico del metodo.

Basta cambiare dynamic a = 123 a int a = 123 e il codice funzionerà. Inoltre, se si modifica la chiamata del metodo a obj2.Hello((int)a);. Infine, digita la variabile come DynamicTarget anziché IDynamicTarget e funzionerà anche tu!

Perché? Quando si lavora con espressioni dinamiche e ci sono più di un overload del metodo con cui la chiamata ha argomenti dinamici, il runtime non sarà in grado di risolvere il sovraccarico da chiamare, poiché la risoluzione di overload del metodo si basa sul tipo e sull'ordine degli argomenti forniti quando è stato chiamato il cosiddetto metodo.

La mia speculazione è la risoluzione di sovraccarico di runtime non riesce quando un'interfaccia implementa anche un'altra interfaccia e il runtime sembra capire che non è possibile garantire che la seconda interfaccia definisca un sovraccarico di una delle altre interfacce che implementa anche, e ti obbliga a fornire il tipo effettivo degli argomenti durante la compilazione.

[...] ma "Ciao" dovrebbe anche essere accessibile da IDynamicTarget, perché estende IDynamicTargetBase.

E 'accessibile, ma il runtime non è in grado di risolvere come fornire gli argomenti del metodo ...