2012-01-28 29 views
5

Tôi là người mới đến Stack Overflow vì vậy hãy dễ dàng đi với tôi! Tôi đang đọc C# trong Depth nhưng tôi đã bắt gặp một kịch bản mà tôi không tin là được bảo hiểm. Tìm kiếm nhanh trên web cũng không làm tăng bất kỳ kết quả nào.Loại suy luận cho các đối số kiểu của các phương thức chung

Nói rằng tôi xác định các phương pháp quá tải sau:

void AreEqual<T>(T expected, T actual) 

void AreEqual(object expected, object actual) 

Nếu tôi gọi AreEqual() mà không chỉ định một đối số kiểu:

AreEqual("Hello", "Hello") 

Sản phẩm phiên bản generic hoặc không chung của phương pháp này gọi? Là phương pháp chung được gọi với đối số kiểu được suy ra, hoặc là phương pháp không chung chung được gọi với các đối số phương thức được ngầm đúc đến System.Object?

Tôi hy vọng câu hỏi của tôi là rõ ràng. Cảm ơn trước cho tất cả lời khuyên.

+5

bạn có thể viết một số mã đơn giản để kiểm tra ... –

+1

http://blogs.msdn.com/b/ericlippert/archive/2009/07/30/generics-are-not-templates.aspx –

+0

@Mitch Wheat - đúng, nhưng sau đó tôi sẽ không phải làm cho bài viết đầu tiên của tôi. Và nó hữu ích cho những người khác để xem câu trả lời ở đây. – zekesteer

Trả lời

5

Các generics có thể tạo ra một hàm AreEqual(string, string). Đây là kết quả gần hơn so với AreEqual(object, object), do đó, do đó chức năng chung được chọn.

Điều thú vị là trình biên dịch sẽ chọn hàm chung này ngay cả khi nó dẫn đến lỗi vi phạm ràng buộc.

Nhìn vào ví dụ này:

using System.Diagnostics; 

namespace ConsoleSandbox 
{ 
    interface IBar 
    { 
    } 

    class Program 
    { 
     static void Foo<T>(T obj1) where T: IBar 
     { 
      Trace.WriteLine("Inside Foo<T>"); 
     } 


     static void Foo(object obj) 
     { 
      Trace.WriteLine("Inside Foo Object"); 
     } 

     static void Main(string[] args) 
     { 

      Foo("Hello"); 
     } 
    } 
} 

Thậm chí ĐÂY nó sẽ chọn phiên bản generic so với phiên bản không chung chung. Và sau đó bạn nhận được lỗi này:

The type 'string' cannot be used as type parameter 'T' in the generic type or method 'ConsoleSandbox.Program.Foo(T)'. There is no implicit reference conversion from 'string' to 'ConsoleSandbox.IBar'.

Nhưng nếu bạn thêm chức năng Foo(string obj1) nó sẽ hoạt động.

+0

Câu trả lời hay, cảm ơn! Ví dụ tốt đẹp, tôi đã thử nó bản thân mình chỉ để xác nhận :-) – zekesteer

+0

Lưu ý rằng độ phân giải quá tải được thực hiện bởi trình biên dịch C#, không phải là khuôn khổ .NET. – phoog

+0

@phoog - cảm ơn, tôi đã thay đổi từ ngữ –

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