2009-03-02 44 views

Trả lời

15

Eric Lippert có tốt article về điều này. Trong trường hợp bạn không thể bị làm phiền khi đọc toàn bộ bài viết, câu trả lời là: trả về giao diện.

+0

+1 Có thể đã đăng liên kết đó nếu bạn chưa thực hiện nó. –

+0

Tìm thấy tuyệt vời! Tôi đang đọc nó ngay bây giờ. Cảm ơn! – Pwninstein

0

Sử dụng Generics. Thật dễ dàng để tương tác với các lớp sưu tập khác và hệ thống kiểu có thể giúp bạn với các lỗi tiềm năng hơn.

Kiểu cũ trả về mảng là một cái nạng trước khi dùng thuốc generic.

3

Luôn trả về loại giao diện trình bày số lượng chức năng lớn nhất cho người gọi. Vì vậy, trong trường hợp của bạn ICollection<YourType> nên được sử dụng.

Một điều thú vị cần lưu ý là các nhà phát triển BCL thực sự đã nhận sai ở một số nơi trong khung công tác .NET - xem this Eric Lippert blog post cho câu chuyện đó.

+0

Như ông nói, họ đã không nhận được nó sai, nhưng họ không có Generics có sẵn như là một tùy chọn (họ giới thiệu trong CLR 2.0). – erikkallen

+0

Tôi biết những gì bạn đang nhận được tại nhưng để trích dẫn bài viết: "Hãy để tôi cung cấp cho bạn một ví dụ về nơi chúng tôi đã nhận được rằng sai lầm khủng khiếp trong một cách rất có thể nhìn thấy trong khuôn khổ." :) –

6

Tại sao không List<T>?

Từ bài Eric Lippert đề cập bởi những người khác, tôi nghĩ rằng tôi sẽ làm nổi bật này:

Nếu tôi cần một chuỗi Tôi sẽ sử dụng IEnumerable<T>, nếu tôi cần một ánh xạ từ các số tiếp giáp với dữ liệu tôi sẽ sử dụng List<T>, nếu tôi cần ánh xạ trên dữ liệu tùy ý, tôi sẽ sử dụng Dictionary<K,V>, nếu tôi cần một bộ tôi sẽ sử dụng HashSet<T>. Tôi chỉ không cần mảng cho bất kỳ thứ gì, vì vậy tôi hầu như không bao giờ sử dụng chúng. Chúng không giải quyết được vấn đề Tôi có tốt hơn các công cụ khác tại xử lý của tôi.

+0

Vâng nó phụ thuộc vào những gì bạn cần làm với giá trị trả lại. IList và Danh sách không có cùng một tập hợp các phương thức sẵn có (Danh sách có nhiều phương thức khả dụng hơn). Nếu bạn không cần bất kỳ phương pháp nào trả về khoảng trống IList thì giải pháp tốt hơn vì quy tắc chung của ngón tay cái là trả về kiểu suy luận các hạn chế nhỏ nhất. Tuy nhiên có một sự khác biệt lớn giữa việc sử dụng/đối số, variabl cục bộ) và trả về. khi bạn sử dụng một cái gì đó bạn biết làm thế nào nó được sử dụng, khi bạn trả lại một cái gì đó bạn không thể chắc chắn về việc sử dụng trả lại –

0

Điều gì làm cho mã của bạn dễ đọc hơn, dễ bảo trì và dễ dàng hơn cho BẠN. Tôi đã sử dụng mảng đơn giản, đơn giản hơn == phần lớn thời gian. Mặc dù tôi thực sự phải xem ngữ cảnh để đưa ra câu trả lời đúng.

4
return ICollection<type> 

Lợi thế đối với loại trả về chung là bạn có thể thay đổi triển khai cơ bản mà không thay đổi mã sử dụng mã đó. Lợi thế để trả về loại cụ thể, là bạn có thể sử dụng nhiều phương thức cụ thể hơn.

1

Tại sao không IList<MyType>?

Nó hỗ trợ lập chỉ mục trực tiếp là dấu hiệu cho một mảng mà không loại bỏ khả năng trả lại List<MyType> một số ngày. Nếu bạn muốn tắt tính năng này, bạn có thể muốn trả lại IEnumerable<MyType>.

5

Nếu bộ sưu tập đang được trả về là chỉ đọc, có nghĩa là bạn không bao giờ muốn các thành phần trong bộ sưu tập được thay đổi, sau đó sử dụng IEnumerable<T>. Đây là biểu diễn cơ bản nhất của một chuỗi chỉ đọc không thay đổi (ít nhất là từ quan điểm của các phần tử đếm chính nó).

Nếu bạn muốn nó là bộ sưu tập khép kín có thể thay đổi, hãy sử dụng ICollection<T> hoặc IList<T>.

Ví dụ: nếu bạn muốn trả về kết quả tìm kiếm một tập hợp tệp cụ thể, sau đó trả lại IEnumerable<FileInfo>.

Tuy nhiên, nếu bạn muốn hiển thị các tệp trong một thư mục, tuy nhiên, bạn sẽ phơi bày IList/ICollection<FileInfo> vì bạn có thể muốn thay đổi nội dung của bộ sưu tập.

+0

IEnumerabl là _not_ một bộ sưu tập chỉ đọc. Đó là một giao diện chung cho một chuỗi và các yếu tố không thay đổi hoặc không phụ thuộc vào các đối tượng của T là bất biến hay không. bất kỳ đối tượng nào của Danh sách là một số điện thoại IE2 có thể là nhưng chắc chắn không làm cho Danh sách một bộ sưu tập chỉ đọc –

+0

@runefs: Bạn đã đọc sai. Tôi không nói về sự bất biến của các thể hiện được trả về, mà đúng hơn là sự bất biến của chính nó. – casperOne

0

Có lợi thế lớn để ưu tiên IEnumerable hơn bất kỳ điều gì khác, vì điều này mang đến cho bạn khả năng triển khai linh hoạt nhất và cho phép bạn sử dụng các toán tử yield return hoặc LINQ để triển khai chậm.

Nếu người gọi muốn List<T> thay vào đó, họ có thể chỉ cần gọi ToList() về bất kỳ thứ gì bạn đã quay trở lại và hiệu suất tổng thể sẽ gần như giống như bạn đã tạo và trả lại List<T> mới từ phương thức của bạn.

0

Mảng có hại, nhưng ICollection<T> cũng có hại.

ICollection<T> không thể đảm bảo đối tượng sẽ không thay đổi.

Tôi đề nghị là để bọc các đối tượng trở về với ReadOnlyCollection<T>

12

Return một IEnumerable<T> sử dụng một yield return.

+0

Đề nghị thú vị, tôi thậm chí không bao giờ nghĩ về điều đó. –

+0

Tôi đã bắt đầu sử dụng rất nhiều, và nó thực sự làm cho một số mã thực sự thanh lịch với LINQ. –

+0

+1 Tôi không đồng ý cho đến khi bạn thêm "sử dụng lợi nhuận". Các khối Iterator là một công cụ rất mạnh mẽ, nếu được sử dụng đúng cách, có thể hợp lý hóa mã của bạn và dấu chân bộ nhớ của bạn. –

8

Tôi sẽ trả lại IList<T> vì điều đó mang lại cho người tiêu dùng chức năng của bạn sự linh hoạt lớn nhất. Bằng cách đó, nếu người tiêu dùng của hàm của bạn chỉ cần liệt kê chuỗi họ có thể làm như vậy, nhưng nếu họ muốn sử dụng trình tự như một danh sách, họ cũng có thể làm điều đó.

Quy tắc chung của tôi là chấp nhận loại ít hạn chế nhất làm thông số và trả lại loại giàu nhất có thể. Đây là, tất nhiên, một hành động cân bằng như bạn không muốn khóa mình vào bất kỳ giao diện cụ thể hoặc thực hiện (nhưng luôn luôn, luôn luôn cố gắng sử dụng một giao diện).

Đây là phương pháp ít được cho là nhất mà bạn, nhà phát triển API, có thể thực hiện. Bạn không quyết định cách người tiêu dùng của chức năng của bạn sẽ sử dụng những gì họ gửi cho bạn - đó là lý do tại sao bạn sẽ trả lại IList<T> trong trường hợp này để mang đến cho họ sự linh hoạt lớn nhất. Cũng vì lý do này, bạn sẽ không bao giờ giả sử biết loại thông số mà người tiêu dùng sẽ gửi cho bạn. Nếu bạn chỉ cần lặp lại một chuỗi được gửi đến bạn dưới dạng tham số thì hãy đặt tham số là IEnumerable<T> thay vì một số List<T>.


EDIT (monoxide): Vì nó không giống như các câu hỏi sẽ được đóng lại, tôi chỉ muốn thêm một liên kết từ các câu hỏi khác về vấn đề này: Why arrays are harmful

+0

Cũng nói. – Shog9

1

Nó phụ thuộc về những gì bạn định làm với bộ sưu tập bạn đang quay trở lại.Nếu bạn chỉ đang lặp lại hoặc nếu bạn chỉ muốn người dùng lặp lại, thì tôi đồng ý với @Daniel, trả lại IEnumerable<T>. Tuy nhiên, nếu bạn thực sự muốn cho phép các hoạt động dựa trên danh sách, tôi sẽ trả về IList<T>.

5

Một mảnh tốt lời khuyên mà tôi đã thường được nghe trích dẫn là:

Hãy tự do trong những gì bạn chấp nhận, chính xác những gì bạn cung cấp.

Về mặt thiết kế API của bạn, tôi khuyên bạn nên trả lại Giao diện chứ không phải là loại cụ thể.

Lấy phương pháp ví dụ của bạn, tôi muốn viết lại nó như sau:

public IList<object> Foo() 
{ 
    List<object> retList = new List<object>(); 
    // Blah, blah, [snip] 
    return retList; 
} 

Điều quan trọng là sự lựa chọn thực hiện nội bộ của bạn - sử dụng một danh sách - không được tiết lộ cho người gọi, nhưng bạn trả lại một giao diện thích hợp.

Nguyên tắc riêng của Microsoft về phát triển khuôn khổ đề xuất chống lại các loại cụ thể, giao diện ưu tiên. (Xin lỗi, tôi không thể tìm thấy liên kết cho điều này)

Tương tự, thông số của bạn phải càng chung càng tốt - thay vì chấp nhận một mảng, chấp nhận một loại IEnumerable thích hợp. Điều này tương thích với mảng cũng như danh sách và các loại hữu ích khác.

Lấy phương pháp dụ của bạn một lần nữa:

public IList<object> Foo(IEnumerable<object> bar) 
{ 
    List<object> retList = new List<object>(); 
    // Blah, blah, [snip] 
    return retList; 
} 
Các vấn đề liên quan