2013-04-12 32 views
13

Tôi nghĩ rằng phương pháp được gọi là quyết định thời gian chạy, hoặc tôi đã bỏ lỡ một cái gì đó? Mẫu mã:Tại sao phương pháp quá tải không được gọi?

class Program 
{ 
    static void Main(string[] args) 
    { 
     var magic = new MagicClass(); 
     magic.DoStuff(new ImplA()); 
     magic.DoStuff(new ImplB()); 
     Console.ReadLine(); 
    } 
} 
class MagicClass 
{ 
    internal void DoStuff<T>(T input) where T : SomeBase 
    { 
     HiThere(input); 
    } 

    void HiThere(SomeBase input) 
    { 
     Console.WriteLine("Base impl"); 
    } 

    void HiThere(ImplA input) 
    { 
     Console.WriteLine("ImplA"); 
    } 

    void HiThere(ImplB input) 
    { 
     Console.WriteLine("ImplB"); 
    } 
} 

abstract class SomeBase 
{ 

} 
class ImplA : SomeBase{} 
class ImplB : SomeBase{} 

Tôi nghĩ tôi sẽ nhận được:

ImplA 
ImplB 

như đầu ra nhưng nó in Base impl. Có bất cứ điều gì tôi có thể làm để có được phương pháp quá tải mà không cần đúc đầu vào?

+2

Đây là một lời giải thích khá hợp lý tại sao: http://csharpindepth.com/Articles/General/Overloading.aspx –

Trả lời

18

Quá tải được chọn bởi trình biên dịch. Để gọi điện thoại tại đây:

internal void DoStuff<T>(T input) where T : SomeBase 
{ 
    HiThere(input); 
} 

chọn một số có SomeBase, vì đó là tất cả những gì có lúc biên dịch.

Điều bạn có thể muốn nhất là ghi đè. Điều này có nghĩa là logic khác nhau phải được đưa vào kế thừa của SomeBase:

abstract class SomeBase 
{ 
    abstract string Name { get; } 
} 
class ImplA : SomeBase{ override string Name { get { return "ImplA"; } } } 
class ImplB : SomeBase{ override string Name { get { return "ImplB"; } } } 

void HiThere(SomeBase input) 
{ 
    Console.WriteLine(input.Name); 
} 
+2

Một khả năng khác là anh ấy muốn làm ['double dispatch'] (http: //en.wikipedia. org/wiki/Double_dispatch) hoặc sử dụng [mô hình khách truy cập'] (http://en.wikipedia.org/wiki/Visitor_pattern). –

+6

Hoặc sử dụng 'dynamic':' HiThere ((năng động) đầu vào); 'Điều này di chuyển độ phân giải quá tải đến thời gian chạy, nơi chính xác loại' đầu vào' được biết đến. –

+0

@DanielHilgarth: Đó có lẽ là cách triển khai tốt nhất có thể có của công văn kép. :) –

4

Quá tải được chọn trong khi biên dịch.
Ghi đè được chọn trong thời gian chạy.

Ở đây, trình biên dịch chỉ biết rằng T có thể được gán cho SomeBase, nhưng không có gì khác. Trên thực tế, nếu nó hoạt động như bạn mong đợi, bạn sẽ có thể hoàn toàn bỏ qua phần where T : SomeBase. Lý do bạn cần nó là trình biên dịch cần phải biết thông tin đó để kiểm tra những gì có thể được gọi trên đối tượng được cung cấp.

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