2015-01-25 36 views
7

Trong khi điều tra cách hoạt động của từ khóa động C#, tôi tình cờ gặp một số hành vi lạ. Nó gần như trông giống như một con bọ, nhưng có lẽ nhiều khả năng là có một lý do cho hành vi đó.Hành vi năng động lạ C#

Trong mã bên dưới, có hai cuộc gọi, một đến obj1 và một đến obj2, nhưng chỉ một trong số chúng thực thi chính xác. Dường như kiểu biến cục bộ là lý do, nhưng "Hello" cũng có thể truy cập được từ IDynamicTarget, vì nó mở rộng 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

vẻ để làm việc trên Mono: http://ideone.com/PGn3Jp. Đây là một phiên bản thất bại trên .Net Fiddle: https://dotnetfiddle.net/55ZMAG – Kobi

+2

Đây là một lỗi địa ngục để bỏ qua nó trong năm năm nay. –

+0

BTW là một lỗi ưu tiên thấp vì nếu đối số là biên dịch- thời gian đã nhập, cùng một mã trong câu hỏi này sẽ hoạt động. Tôi cảm thấy rằng có vài trường hợp bạn đưa ra một đối số năng động ... –

Trả lời

0

Có vẻ như đó là vấn đề về giải pháp quá tải phương thức.

Chỉ cần thay đổi dynamic a = 123 thành int a = 123 và mã của bạn sẽ hoạt động. Ngoài ra, nếu bạn thay đổi cuộc gọi phương thức thành obj2.Hello((int)a);. Cuối cùng, hãy nhập biến là DynamicTarget thay vì IDynamicTarget và biến này cũng sẽ hoạt động!

Tại sao? Khi bạn làm việc với các biểu thức động và có nhiều hơn một phương thức quá tải mà invokation có các đối số động, thời gian chạy sẽ không thể giải quyết tình trạng quá tải để gọi, vì phương thức quá tải phân giải dựa trên loại và thứ tự của các đối số được cung cấp khi cái gọi là phương pháp được gọi.

Suy đoán của tôi là độ phân giải quá tải thời gian không thành công khi giao diện cũng thực hiện giao diện khác và thời gian chạy dường như hiểu rằng không có gì đảm bảo rằng giao diện thứ hai sẽ xác định tình trạng quá tải của một trong các giao diện khác cũng thực hiện. buộc bạn phải cung cấp loại đối số thực tế trong thời gian biên dịch.

[...] nhưng "Hello" cũng phải được truy cập từ IDynamicTarget, vì mở rộng IDynamicTargetBase.

Nó có thể truy cập, nhưng thời gian chạy là không thể giải quyết như thế nào để cung cấp luận cứ phương pháp của ...