2015-01-25 10 views
7

При исследовании того, как работает ключевое слово C#, я наткнулся на какое-то странное поведение. Это почти похоже на ошибку, но, скорее всего, есть причина для поведения.Weird C# динамическое поведение

В приведенном ниже коде есть два вызова: один для obj1 и один для obj2, но только один из них выполняется правильно. Похоже, что причиной является локальный тип переменной, но «Hello» также должен быть доступен из IDynamicTarget, поскольку он расширяет 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

Кажется, работает на Mono: http://ideone.com/PGn3Jp. Вот версия, которая терпит неудачу .Net Fiddle: https://dotnetfiddle.net/55ZMAG – Kobi

+2

Это одна черта ошибки, которая игнорируется в течение пяти лет. –

+0

BTW - ошибка с низким приоритетом, потому что если аргумент компилируется, набрал время, тот же код в этом вопросе будет работать. Я чувствую, что есть несколько случаев, когда вы даете динамический аргумент ... –

ответ

0

Похоже, что это проблема с проблемой перегрузки метода.

Просто измените dynamic a = 123 на номер int a = 123 и ваш код будет работать. Кроме того, если вы меняете вызов метода на obj2.Hello((int)a);. Наконец, введите переменную как DynamicTarget вместо IDynamicTarget, и она тоже будет работать!

Почему? Когда вы работаете с динамическими выражениями, и существует более чем перегрузка метода, у которой invokation имеет динамические аргументы, среда выполнения не сможет разрешить перегрузку для вызова, поскольку разрешение перегрузки метода основано на типе и порядке аргументов, предоставляемых при вызывается так называемый метод.

Мое предположение - это ошибка перегрузки во время выполнения, когда интерфейс также реализует другой интерфейс, а время выполнения, похоже, понимает, что нет гарантии, что второй интерфейс определит перегрузку одного из других интерфейсов, который также реализует, и это заставляет вас предоставить фактический тип аргументов (ов) во время компиляции.

[...] но "Hello" также должно быть от IDynamicTarget подъезд, , потому что он расширяет IDynamicTargetBase.

Это доступно, но среда не в состоянии решить, как обеспечить аргументы метода ...