Sự khác biệt giữa Select và ConvertAll trong C #


117

Tôi có một số Danh sách:

List<int> list = new List<int> { 1, 2, 3, 4, 5 };

Tôi muốn áp dụng một số chuyển đổi cho các phần tử trong danh sách của mình. Tôi có thể làm điều này theo hai cách:

List<int> list1 = list.Select(x => 2 * x).ToList();
List<int> list2 = list.ConvertAll(x => 2 * x).ToList();

Sự khác biệt giữa hai cách này là gì?


16
Bạn không cần phải .ToList () sau ConvertAll ().
Gleno

không bao giờ nghe nói về ConvertAll, đã biết một cái gì đó mới ngày hôm nay
Amit Bisht

Câu trả lời:


117

Selectlà một phương thức mở rộng LINQ và hoạt động trên tất cả IEnumerable<T>các đối tượng trong khi chỉ ConvertAllđược thực hiện bởi List<T>. Các ConvertAllphương pháp tồn tại kể từ NET 2.0 trong khi LINQ đã được giới thiệu với 3,5.

Bạn nên ưu tiên Selecthơn ConvertAllvì nó hoạt động cho bất kỳ loại danh sách nào, nhưng về cơ bản chúng đều hoạt động giống nhau.


7
Và những gì về các buổi biểu diễn? Nếu tôi có một Danh sách, sử dụng ConvertAll hoặc Select có hiệu quả hơn không?
Nicolas

@Nicolas: Tổng thời gian thực hiện là như nhau, nhưng chúng thực hiện xử lý khác nhau để phù hợp với các vị trí khác nhau. Tôi đã thêm một số về nó trong câu trả lời của tôi.
Guffa

3
Bạn không thể so sánh SelectConvertAll. Đầu tiên chọn mọi mục theo một trình tự và bạn có thể tự do làm bất cứ điều gì bạn muốn với nó. Sau này có một ý định rõ ràng: chuyển đổi mặt hàng này sang mặt hàng khác.
Tim Schmelter

1
Ngoài ra, lớp List <T> chứa một số phương thức gần như khớp chính xác trong LINQ. Tồn tại -> Bất kỳ, Tìm -> Thứ nhất, FindAll -> ở đâu, FindLast -> ngoái, TrueForAll -> All
Mikal Schacht Jensen

Sự khác biệt giữa ConvertAll và Select là ConvertAll sẽ phân bổ kích thước của danh sách trước tay. Đối với một chuỗi lớn, điều này sẽ tạo ra sự khác biệt về hiệu suất. Do đó, nếu hiệu suất là mục tiêu của bạn, hãy sử dụng ConvertAll. Nếu hiệu suất không phải là mối quan tâm, hãy sử dụng Chọn vì nó dễ thành ngữ hơn trong ngôn ngữ và cho người đọc biết hiệu suất trong tương lai không phải là mối quan tâm.
Durdsoft

82

ConvertAllkhông phải là một phần mở rộng, nó là một phương thức trong lớp danh sách. Bạn không cần phải gọi ToListkết quả vì nó đã là một danh sách:

List<int> list2 = list.ConvertAll(x => 2 * x);

Vì vậy, sự khác biệt là ConvertAllphương thức chỉ có thể được sử dụng trên một danh sách và nó trả về một danh sách. Các Selectphương pháp có thể được sử dụng trên bất kỳ bộ sưu tập mà cụ các IEnumerable<T>giao diện, và nó trả về mộtIEnumerable<T> .

Ngoài ra, họ xử lý khác nhau, vì vậy họ có thế mạnh của mình trong các tình huống khác nhau. Các ConvertAllphương pháp chạy qua danh sách và tạo ra một danh sách mới trong một đi, trong khi Selectphương pháp sử dụng thực hiện lười biếng và chỉ xử lý các mặt hàng như bạn cần họ. Nếu bạn không cần tất cả các mục, Selectphương pháp hiệu quả hơn. Mặt khác, khi ConvertAllđã trả lại danh sách, bạn không cần phải giữ lại danh sách ban đầu.


Có thể cho rằng, người ta không bao giờ phải "giữ danh sách ban đầu": nó sẽ được thực hiện khi cần thiết bởi GC.
user2864740

8
@ user2864740: Đúng, điều đó đúng nếu nguồn hoàn toàn là một danh sách trong bộ nhớ. Nếu nó được đọc từ một tệp, ví dụ, bạn cần giữ tệp mở cho đến khi bạn xử lý kết quả từ Select.
Guffa

19

Câu trả lời đầu tiên không nên là câu được chấp nhận. Tôi là cựu MVP C # Microsoft 2007.

Ngược lại với phản hồi được chấp nhận, ConvertAllhiệu quả hơn nhiều so với sự kết hợp của SelectToList() .

Đầu tiên, ConvertAll nó hoàn toàn nhanh hơn và nó sử dụng lượng bộ nhớ tối thiểu để làm như vậy. Tương tự như Array.ConvertAll vs Select và ToArray. Điều này sẽ rõ ràng hơn nhiều với một mảng có độ dài lớn hơn hoặc nhiều lệnh gọi trong một vòng lặp.

1) ConvertAllbiết kích thước của danh sách cuối cùng và tránh phân bổ lại mảng cơ sở.ToList() sẽ tiếp tục thay đổi kích thước mảng nhiều lần.

2) ToListsẽ thực hiện IEnumerable<>các cuộc gọi giao diện chậm hơn , trong khiConvertAll sẽ lặp qua mảng bên dưới mà không có lệnh gọi bổ sung hoặc kiểm tra phạm vi.

3) Chọn sẽ tạo thêm một IEnumerable<T>đối tượng.


1

Tôi biết điều này là hơi muộn nhưng tôi vẫn bổ sung vì điều này có thể có ích cho những người khác trong tương lai.

Khi sử dụng nó trong biểu thức truy vấn EntityFramework, bạn không nên sử dụng ConvertAll () vì nó đánh giá biểu thức hơn là để nó dưới dạng biểu thức để sử dụng trong tương lai. Điều này làm giảm nghiêm trọng hiệu suất thực thi truy vấn cơ sở dữ liệu vì nó sẽ phải thực hiện số lượng lệnh gọi trước khi đánh giá biểu thức cuối cùng.


9
Không hẳn. Như Guffa chỉ ra trong câu trả lời này , ConvertAll là một phương pháp trênList<T> . Vào thời điểm bạn danh sách, bạn đã đánh giá biểu thức của mình. Nhưng bạn đúng - nếu bạn không muốn đánh giá tất cả, Selectthì tốt hơn.
Wai Ha Lee
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.