2011-02-05 29 views
18

Tôi nhận thấy điều này ngày khác, nói rằng bạn có hai phương pháp quá tải:Phương pháp giải quyết tình trạng quá tải liên quan đến Generics và IEnumerable

public void Print<T>(IEnumerable<T> items) { 
    Console.WriteLine("IEnumerable T"); 
} 
public void Print<T>(T item) { 
    Console.WriteLine("Single T"); 
} 

Mã này:

public void TestMethod() { 
    var persons = new[] { 
     new Person { Name = "Yan", Age = 28 }, 
     new Person { Name = "Yinan", Age = 28 } 
    }; 
    Print(persons); 
    Print(persons.ToList()); 
} 

in:

Single T 
Single T 

Tại sao là Person[]List<Person> phù hợp hơn với T hơn chúng là IEnumerable<T> trong những trường hợp này?

Cảm ơn,

UPDATE: Ngoài ra, nếu bạn có quá tải khác

public void Print<T>(List<T> items) { 
    Console.WriteLine("List T"); 
} 

Print(persons.ToList()); sẽ thực sự in List T thay vì Single T.

+2

Gọi 'In (người như IEnumerable );' nên gọi phương thức khác.Tra cứu phương thức chung không thực hiện một phép diễn xuất ngầm từ 'Person []' tới 'IEnumerable '. Khi bạn gọi 'person.ToList()', kiểu ngay lập tức của bạn là một 'Danh sách ' (cũng không đòi hỏi phải có diễn viên ngầm). –

+0

+1 Tôi đã không quan tâm đến vấn đề này một chút. – Dan

Trả lời

17

Phần đầu tiên của câu hỏi của bạn (không có quá tải Danh sách cụ thể) thật dễ dàng. Chúng ta hãy xem xét các cuộc gọi Array, bởi vì nó hoạt động tương tự cho cả hai cuộc gọi:

Đầu tiên, suy luận kiểu tạo ra hai triển khai chung có thể có của cuộc gọi: Print<Person[]>(Person[] items)Print<Person>(IEnumerable<Person> items).

Sau đó, quá trình phân giải quá tải sẽ khởi động, vì lần thứ hai yêu cầu chuyển đổi ngầm, trong đó giá trị đầu tiên không (xem §7.4.2.3 của thông số C#). Cơ chế tương tự hoạt động cho biến thể Danh sách.

Với quá tải thêm, có thể xảy ra tình trạng quá tải có thể xảy ra với lệnh gọi Danh sách: Print<Person>(List<Person> items). Đối số cũng giống như đối số Print<List<Person>>(List<Person> items) nhưng một lần nữa, phần 7.4.3.2 cung cấp độ phân giải bằng ngôn ngữ

Loại được xây dựng cụ thể hơn loại được xây dựng khác (với cùng số đối số kiểu) nếu ít nhất một đối số kiểu là cụ thể hơn và không có đối số kiểu nào ít cụ thể hơn đối số kiểu tương ứng trong đối số khác.

Vì vậy, quá tải Print<Person> cụ thể hơn so với quá tải Print<List<Person>> và phiên bản Danh sách thắng trên IEnumerable vì nó không yêu cầu chuyển đổi ngầm.

+0

cảm ơn vì đã đề cập đến việc đúc ngầm, tất cả đều có ý nghĩa bây giờ – theburningmonk

3

Bởi vì các phương pháp được tạo từ generics Print(Person[] item)Print(List<Person> item) phù hợp hơn IEnumerable<T>.

Trình biên dịch được tạo ra những phương pháp dựa trên lập luận kiểu của bạn, vì vậy lớp tổng quát Print<T>(T item) sẽ được biên soạn như Print(Person[] item)Print(List<Person> item) (tốt, bất cứ loại đại diện cho một List<Person> ở biên soạn). Do đó, lời gọi phương thức sẽ được trình biên dịch giải quyết là phương thức cụ thể chấp nhận loại trực tiếp, chứ không phải việc thực hiện Print(IEnumerable<Peson>).

+0

nói cách khác, In sẽ luôn được coi là phù hợp nhất khi thấy T có thể là gì? Nhưng nếu bạn thêm phương thức In (Danh sách mục), đó là phương thức sẽ được gọi cho In (people.ToList) – theburningmonk

+0

Ngoài ra, theo bài đăng trên blog này của Eric Lippert, đó không phải là cách C# generics hoạt động http://blogs.msdn.com/b/ericlippert/archive/2009/07/30/generics-are-not-templates.aspx những gì bạn mô tả là các mẫu trong C++ – theburningmonk

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