2011-11-15 39 views
7

Tôi vừa vấp phải một vấn đề rất thú vị. Cung cấp mã sau đây:Phương pháp đa hình không hoạt động trên C# 4

using System; 

class Program 
{ 
    class A { } 
    class B : A { } 

    private static void MyMethod(A a) /* first method */ 
    { 
     Console.WriteLine("A"); ; 
    } 

    private static void MyMethod(B b) /* second method */ 
    { 
     Console.WriteLine("B"); 
    } 

    static void Main(string[] args) 
    { 
     var a = new A(); 
     // Call first method 
     MyMethod(a); 

     A b = new B(); 
     // Should call the second method 
     MyMethod(b); 

     Console.ReadLine(); 
    } 
} 

Tôi hy vọng phương thức thứ hai sẽ được gọi vì kiểu thời gian chạy của biến là B. Bất kỳ ý tưởng nào tại sao mã này gọi phương thức đầu tiên?

Cảm ơn, Tibi

Một số làm rõ: Đa hình nghĩa là nhiều hình thức mà không có gì để làm nơi bạn khai báo phương pháp này.

Quá tải phương thức là một dạng đa hình, đa hình đặc biệt.

Cách đa hình thường được thực hiện bằng cách sử dụng kết buộc muộn.

động là giải pháp cho sự cố này.

Thực tế là điều này không hoạt động trong C# (hoặc Java) nó là một sự phân chia thiết kế mà tôi muốn hiểu tại sao được tạo ra, và không có câu trả lời nào trả lời câu hỏi này.

/Tibi

+4

Đây không phải là đa hình, bạn có hai trường hợp quá tải cùng một phương thức, mỗi trường hợp lấy các loại khác nhau làm tham số. Sau đó, bạn khai báo "b" là A. Trình biên dịch cho phép bạn làm điều này vì B thừa hưởng A. – Maess

Trả lời

6

Quá tải phương thức trong C#, theo mặc định, được xác định tĩnh tại thời gian biên dịch. Vì bạn đang truyền một biến kiểu tĩnh kiểu A, nó sẽ liên kết tĩnh với phương thức với quá tải A. Sử dụng từ khóa động để có được hành vi bạn muốn.

static void Main(string[] args) 
{ 
    dynamic d = new A(); 
    // Call first method 
    MyMethod(d); 

    d = new B(); 
    // Call the second method 
    MyMethod(d); 

    Console.ReadLine(); 
} 
+0

Tôi không nghĩ về điều đó! Cảm ơn. – Tibi

+0

Tôi thực sự không biết rằng từ khóa 'dynamic' gây ra các lời gọi đến các phương thức quá tải để giải quyết trong thời gian chạy, hoặc là điều này rất hữu ích để biết. Tôi rất tò mò về các vấn đề hiệu suất tiềm tàng với loại ràng buộc muộn này. –

+1

Tôi đoán rằng bạn sẽ phát sinh một số lần truy cập hiệu suất trong lần đầu tiên bạn gọi nó bằng loại tham số mới vì nó cần được giải quyết, nhưng sau đó được lưu trong bộ nhớ đệm bằng DLR. – Tibi

14

Đây không phải là ví dụ về đa hình. Đa hình xuất hiện khi bạn gọi phương thức ON đối tượng, không phải khi đối tượng được sử dụng làm tham số. Đây chỉ là một ví dụ đơn giản về quá tải phương thức.

Bạn khai báo b là thuộc loại A, do đó trình biên dịch sẽ liên kết đến quá tải sử dụng loại A. Trình liên kết không quan tâm B là lớp con của A, nó chỉ chọn quá tải với chữ ký cho các loại được khai báo (không phải kiểu thực tế) của các tham số được truyền vào.

nếu bạn muốn ép buộc sử dụng phương thức thứ 2, hãy nhập b vào loại B trong cuộc gọi phương thức.

MyMethod((B)b); 
+0

Thực vậy. Điều tương tự cũng xảy ra trong Java. Hành vi mong đợi. – EdH

+0

Trong một tình huống đúc phức tạp hơn sẽ chỉ làm cho mã xấu xí. Dù sao, tôi sẽ mong đợi các mối liên kết để quan tâm đến loại tham số và sử dụng cuối ràng buộc thay thế. – Tibi

+1

Nếu bạn muốn nó hoạt động theo cách bạn nên đặt phụ 'DoSomething' vào' A' và ghi đè nó trong 'B'. Sau đó, khi bạn gọi 'b.DoSomething()' nó sẽ chọn đúng dựa trên kiểu thực tế. –

0

Không gọi phương thức thứ hai vì tham chiếu đến b là loại A. Trong khi b chứa tham chiếu đến một thể hiện của B, đó không phải là loại thực tế là B, do đó, quá tải sử dụng tham chiếu A được chọn.

+0

Tôi hiểu chính xác những gì nó làm, tôi chỉ không hiểu tại sao. – Tibi

+1

Cuộc gọi phương thức được giải quyết tại thời gian biên dịch. (Các phương thức 'kiểu động 'được loại trừ) Đó là lý do tại sao. – recursive

+0

Phương pháp đa hình được giải quyết trong thời gian chạy. – Tibi

Các vấn đề liên quan