Sự khác biệt giữa các Bộ sưu tập Giao diện Chung khác nhau trong C #


11

Tôi đã chơi xung quanh với phát triển C # cho Windows và ASP.net MVC một thời gian rồi. Nhưng tôi vẫn chưa rõ ràng về một vài lĩnh vực. Tôi đang cố gắng tìm hiểu sự khác biệt cơ bản giữa và các vấn đề về hiệu suất với việc sử dụng và hoán đổi các loại Giao diện Bộ sưu tập Chung tương tự .

Sự khác biệt cơ bản giữa là gì IEnumerable<T>, ICollection<T>, List<T>(Class)?

Tôi dường như sử dụng và trao đổi chúng mà không thấy bất kỳ vấn đề nào trong các ứng dụng của mình. Ngoài ra, có bất kỳ bộ sưu tập chung tương tự như thế này có thể được hoán đổi với ba?


2
cũng có IList <T> nữa
jk.

Câu trả lời:


19

Danh sách <T> là một lớp và thực hiện cả giao diện ICollection <T>IEnumerable <T> . Ngoài ra, ICollection <T> mở rộng giao diện <T> IEnumerable. Chúng không thể thay thế cho nhau, ít nhất là không phải từ tất cả các quan điểm.

Nếu bạn có Danh sách <T>, bạn được đảm bảo rằng đối tượng này thực hiện các phương thức và thuộc tính bắt buộc phải được thực hiện bởi giao diện ICollection <T> và IEnumerable <T>. Trình biên dịch biết điều đó và bạn được phép bỏ "xuống" một ICollection <T> hoặc IEnumerable <T>. Tuy nhiên, nếu bạn có ICollection <T>, trước tiên bạn phải kiểm tra rõ ràng mã của mình cho dù đó là Danh sách <T> hay thứ gì khác, có lẽ là Từ điển <T> (trong đó T là KeyValuePair ) trước khi chuyển nó thành gì khao khát.

Bạn biết rằng ICollection mở rộng IEnumerable, vì vậy bạn có thể bỏ nó xuống IEnumerable. Nhưng nếu bạn chỉ có một IEnumerable, một lần nữa bạn không được đảm bảo rằng đó là Danh sách. Nó có thể, nhưng nó có thể là một cái gì đó khác. Bạn nên mong đợi một ngoại lệ truyền không hợp lệ nếu bạn cố gắng đưa Danh sách <T> sang Từ điển <T> chẳng hạn.

Vì vậy, chúng không "hoán đổi cho nhau".

Ngoài ra, có rất nhiều giao diện chung, hãy kiểm tra những gì bạn có thể tìm thấy trong không gian tên System.Collections.Generic .

Chỉnh sửa: liên quan đến nhận xét của bạn, hoàn toàn không có hình phạt về hiệu suất nếu bạn sử dụng Danh sách <T> hoặc một trong các giao diện mà nó thực hiện. Bạn vẫn sẽ cần tạo một đối tượng mới, kiểm tra đoạn mã sau:

List<T> list = new List<T>();
ICollection<T> myColl = list;
IEnumerable<T> myEnum = list;

list , myCollmyEnum đều trỏ đến cùng một đối tượng. Cho dù bạn khai báo nó dưới dạng Danh sách hay ICollection hay IEnumerable tôi vẫn yêu cầu chương trình tạo Danh sách. Tôi có thể đã viết điều này:

ICollection<T> myColl = new List<T>();

myColl , tại thời gian chạy vẫn là một Danh sách.

Tuy nhiên , đây là điểm quan trọng nhất ... để giảm khớp nối và tăng khả năng bảo trì, bạn nên luôn luôn khai báo các biến và tham số phương thức bằng cách sử dụng mẫu số thấp nhất có thể cho bạn, cho dù đó là giao diện hay lớp trừu tượng hay cụ thể.

Hãy tưởng tượng rằng điều duy nhất mà phương thức "PerformanceOperation" cần là liệt kê các phần tử, thực hiện một số công việc và thoát, trong trường hợp đó bạn không cần thêm hàng trăm phương thức có sẵn trong Danh sách <T>, bạn chỉ cần những gì có sẵn trong IEn Countable <T >, vì vậy những điều sau đây nên được áp dụng:

public void PerformOperation(IEnumerable<T> myEnumeration) { ... }

Bằng cách đó, bạn và các nhà phát triển khác biết rằng bất kỳ đối tượng nào của lớp đang thực hiện giao diện <T> IEnumerable đều có thể được cung cấp cho phương thức này. Nó có thể là Danh sách, Từ điển hoặc lớp bộ sưu tập tùy chỉnh mà nhà phát triển khác đã viết.

Nếu ngược lại, bạn xác định rõ ràng bạn cần một Danh sách cụ thể <T> (và mặc dù hiếm khi xảy ra trong cuộc sống thực, nó vẫn có thể xảy ra), bạn và các nhà phát triển khác biết rằng đó phải là Danh sách hoặc một lớp cụ thể khác kế thừa từ Danh sách.


Trước hết cảm ơn. Bây giờ, điểm quan tâm là làm thế nào để quyết định sử dụng ?? Vì Danh sách <T> thực hiện cả hai giao diện, tại sao không phải lúc nào cũng sử dụng nó ở mọi nơi yêu cầu IEnumerable hoặc ICollection. Luôn luôn sử dụng danh sách có ảnh hưởng hiệu suất? Vui lòng chỉnh sửa câu trả lời của bạn để trả lời cho những lo ngại này
Pankaj Upadhyay

Tôi đã chỉnh sửa để trả lời các câu hỏi về hiệu suất của bạn
Jalayn

+1, nhưng tôi sẽ thêm rằng trong những trường hợp hiếm hoi mà bạn thực sự cần phải truyền danh sách cho một phương thức, bạn nên sử dụng IListchứ không phải Listtrong khai báo phương thức.
Konamiman

@Konamiman - Tùy thuộc nếu bạn cần List<>chức năng cụ thể, như thế nào .AddRange(). Việc IList<>không phơi bày điều đó.
Bobson

6

Hãy xem các trang MSDN cho ICollectionIEnumerable .

Nói một cách rất trừu tượng, đây là cách tôi hình dung về các loại này.

Một IEnumerable là bất cứ điều gì có thể được liệt kê - đó là, lặp đi lặp lại. Nó không nhất thiết có nghĩa là một "bộ sưu tập"; ví dụ, một IQueryable thực hiện IEnumerable và nó không phải là một bộ sưu tập, nhưng là thứ có thể được truy vấn để trả về các đối tượng. Để thực hiện IEnumerable, một đối tượng chỉ cần có thể trả về một đối tượng khi được truy vấn. Tôi có thể nói rằng tôi có vô số nhiệm vụ mà tôi sẽ thực hiện hôm nay (nó không phải là một danh sách vì tôi đã không viết nó ra hoặc xây dựng nó, nhưng tôi có thể nói cho bạn biết tôi sẽ làm gì bây giờ và nếu bạn hỏi 'và sau đó?' tôi có thể nói cho bạn biết nhiệm vụ sau).

Một ICollection cụ thể hơn một IEnumerable. Một điểm khác biệt chính là Bộ sưu tập biết có bao nhiêu mặt hàng; để biết có bao nhiêu mục trong một Số lượng bạn thực hiện một cách hiệu quả và đếm chúng:

Tôi: Các bạn, mỗi bạn có bao nhiêu món đồ?

Vô số: Tôi không thực sự biết. Vâng, đây là một mục. Tôi đã có một cái khác, vì vậy đó là hai. Và một cái khác, vì vậy đó là ba ... và một cái khác ... ok vậy đó là 2382. Không còn vật phẩm nào nữa, vì vậy tôi đã nhận được 2382. Đừng hỏi tôi nữa vì tôi sẽ phải trải qua tất cả chúng một lần nữa.

Bộ sưu tập: Tôi đã có 2382 mặt hàng. Tôi đã biết điều đó.

Một bộ sưu tập thường là một cái gì đó đã biết tất cả các yếu tố của nó ở đâu và sẽ không phải đi và tìm hoặc tạo chúng khi bạn yêu cầu chúng. Nó ... cụ thể hơn cả Vô số.

Theo tôi, sự khác biệt giữa Bộ sưu tập và Bộ sưu tập lớn hơn nhiều so với sự khác biệt giữa Bộ sưu tập và Danh sách. Trong thực tế, tôi đang đấu tranh để nghĩ về một sự khác biệt thực tế giữa Bộ sưu tập và Danh sách, nhưng tôi tin rằng Danh sách cung cấp các phương pháp tốt hơn để tìm kiếm và đặt hàng.

Các loại Bộ sưu tập khác bao gồm QueueStack, cũng như Dictionary.

Tên của các loại này khá hữu ích - bạn có thể hình dung ra một hàng đợi và một ngăn xếp như các đối tác trong thế giới thực của chúng và xem xét sự khác biệt mà bạn có thể có trong Danh sách.


"Tôi đang đấu tranh để nghĩ về một sự khác biệt thực tế giữa Bộ sưu tập và Danh sách" ... Sau đó, trong câu trả lời của bạn, bạn tự trả lời câu hỏi này. Một Listlà một ICollection, mà là một ICollectionkhông phải là luôn luôn là một List( Queue, Stack, Dictionary, ...)
Steven Jeuris

@Steven Đó là một câu trả lời rất lan man. Tôi đồng ý rằng đây là một sự khác biệt quan trọng, nhưng tôi sẽ không gọi đó là một sự khác biệt thực tế. Nó có ý nghĩa gì với người dùng?
Kirk Broadhurst

Thật dễ dàng! :) Queue<int> queue = (Queue<int>)list;sẽ ném một InvalidCastExceptionkhi listkhông phải là a Queue<int>. Sự khác biệt giữa hàng đợi và danh sách nằm ngoài phạm vi của câu hỏi này.
Steven Jeuris

Không phải là khía cạnh quan trọng của IEnumerable rằng nó có thể trả về các mục hiện tạitiếp theo - bạn có thể ám chỉ điều đó, nhưng đừng nói rõ ràng như vậy. Về cơ bản, một cái gì đó thực hiện IEnumerable một mình không thể trả lại một mục tùy ý của các thành viên của nó khi được truy vấn - chỉ có mục hiện tại và mục tiếp theo.
cori

@cori Đó là một cách rất ngắn gọn để đặt nó, rõ ràng hơn nhiều so với câu trả lời của tôi.
Kirk Broadhurst

-1

Có thể truy vấn:

truy vấn không được thực thi cho đến khi thực sự lặp lại các mục, có thể bằng cách thực hiện .ToList ()

Vô số:

danh sách chỉ các mục. Bạn không thể nhận được tại "mục 4" mà không vượt qua các mục 0-3. danh sách chỉ đọc, bạn không thể thêm vào nó hoặc xóa khỏi nó. Vẫn có thể sử dụng thực thi hoãn lại.

IList:

truy cập ngẫu nhiên vào danh sách đầy đủ hoàn toàn trong bộ nhớ hỗ trợ thêm và xóa

ICollection:

Là giữa IEnumerable và IList. "Tốt nhất" là gì tùy thuộc vào yêu cầu của bạn. Thông thường mặc dù IEnumerable là "đủ tốt" nếu bạn chỉ muốn hiển thị các mục. Ít nhất là luôn luôn sử dụng các biến thể chung.


câu trả lời này dường như không thêm bất cứ điều gì có giá trị vào những gì đã được đăng trong các câu trả lời trước đó
gnat

đó chỉ là một khái niệm đơn giản về tất cả
Zia Qammar
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.