2010-05-02 8 views
7

Vấn đề của một công văn đơn giản là quen thuộc với những người tham gia vào mã hóa với các ngôn ngữ gõ tĩnh như Java và C#. Ý tưởng cơ bản là:Loại biến 'động' mới trong .NET 4.0 giải quyết vấn đề gửi phương thức đơn/đa trong CLR?

Trong khi đa hình runtime cho phép chúng tôi để gửi đến các phương pháp gọi đúng theo các loại (loại runtime) của receiver, ví dụ:

IAnimal mything = new Cat(); 
mything.chop(); 

Cuộc gọi phương pháp sẽ được thực hiện theo loại thời gian chạy là mything, cụ thể là Cat. Đây là khả năng gửi đơn (có trong Java/C#).

Bây giờ, nếu bạn cần phải gửi không chỉ vào loại thời gian chạy của máy thu, nhưng trên các loại (nhiều) lập luận một trong hai, bạn phải đối mặt với một vấn đề nhỏ:

public class MyAcceptor { 
    public void accept (IVisitor vst) {...} 
    public void accept (EnhancedConcreteVisitor vst) {...} 
} 

Phương pháp thứ hai không bao giờ được gọi , bởi vì trong mã 'người tiêu dùng' của chúng tôi, chúng tôi chỉ có xu hướng xử lý các loại đối tượng khác nhau (khách truy cập trong ví dụ của tôi) bởi siêu kiểu hoặc giao diện phổ biến của họ.

Đó là lý do tại sao tôi hỏi - vì gõ năng động cho phép các công văn đa hình nhiều và C# 4.0 có từ khóa năng động;)

+5

Vấn đề gửi đơn/đa phương thức là gì? –

+0

Tôi sẽ cập nhật câu hỏi của mình bằng liên kết wikipedia) – Bubba88

+0

Huh, là câu hỏi _that_ way stupid? Hoặc tôi chỉ bỏ lỡ một cái gì đó? – Bubba88

Trả lời

12

Có, nhập động cho phép nhiều công văn - và không, bạn không phải tạo đối tượng động của riêng mình để thực hiện.

Giả sử chúng tôi muốn tự mình thực hiện Enumerable.Count() và chúng tôi không muốn tải các thử nghiệm "if (source is IList)" trong mã của chúng tôi. Chúng ta có thể viết nó như thế này:

public static class Enumerable 
{ 
    public static int Count<T>(this IEnumerable<T> source) 
    { 
     dynamic d = source; 
     return CountImpl(d); 
    } 

    private static int CountImpl<T>(ICollection<T> collection) 
    { 
     return collection.Count; 
    } 

    private static int CountImpl(ICollection collection) 
    { 
     return collection.Count; 
    } 

    private static int CountImpl<T>(string text) 
    { 
     return text.Length; 
    } 

    private static int CountImpl<T>(IEnumerable<T> source) 
    { 
     // Fallback 
     int count = 0; 
     foreach (T t in source) 
     { 
      count++; 
     } 
     return count; 
    } 
} 

Tôi không nói rằng nó sẽ là một ý tưởng tốt, nhưng đó là cách nó sẽ làm việc :)

Lưu ý rằng bạn cần phải cẩn thận không để giới thiệu tình huống mà bạn có thể kết thúc với một cuộc gọi mơ hồ đối với một số loại. Đây không phải là một vấn đề khi sử dụng các lớp cho các tham số, nhưng hãy xem xét rằng một lớp đơn có thể thực hiện nhiều giao diện.

+0

ít nhất, một ví dụ hay cho 'động'. – peterchen

+0

Đúng! Đó là những gì tôi đã sau) Cảm ơn lời giải thích và một chút O_o để xem Jon Skeet trả lời câu hỏi của tôi :) – Bubba88