2010-11-15 38 views
11

Tôi ngạc nhiên khi thấy rằng có vẻ như không phải là một phương pháp để thêm một phần tử đơn lẻ vào bộ sưu tập IEnumerable.Cách tốt nhất để thêm phần tử đơn vào bộ sưu tập IEnumerable là gì?

Làm cách nào để thêm một phần tử vào bộ sưu tập IEnumerable?

+0

thể trùng lặp của [? Làm thế nào tôi có thể thêm một mục vào một bộ sưu tập IEnumerable] (http : //stackoverflow.com/questions/1210295/how-can-i-add-an-item-to-a-ienumerablet-collection) – nawfal

Trả lời

23

Bạn thực sự không thể thêm thành phần vào IEnumerable vì nó chỉ được đọc. Tốt nhất là một trong hai cái gì đó như:

return new List<Foo>(enumerable){ new Foo() }; 

hoặc

return enumerable.Concat(new [] { new Foo() }); 
6

Bạn có thể ghép nó với một mảng singleton:

IEnumerable xs; 
xs.Concat(new[]{x}); 
19

Mấu chốt của IEnumerable là nó là một bộ sưu tập phong cách kéo readonly. Nếu bạn muốn, bạn có thể mô phỏng thêm bằng cách làm một cái gì đó như thế này:

public static IEnumerable<T> Add<T>(this IEnumerable<T> source, T additionalItem) 
{ 
    foreach(var item in source) 
    { 
     yield return item; 
    } 

    yield return additionalItem; 
} 
+2

Tôi humbly đề nghị đặt tên phương thức này là "Concat" khi tôi cảm thấy nó truyền đạt ý định của phương pháp tốt hơn "Thêm" có ý nghĩa khá mạnh khi giao dịch với bộ sưu tập S. – GuiSim

+3

'Nối' thậm chí còn tốt hơn. Concat cảm thấy như tham gia với một cái gì đó tương tự, trong khi Add/Append cảm thấy như bổ sung với một cái gì đó (mặc dù Add cảm thấy ít lười biếng) .. – nawfal

+0

Bằng cách nào đó phương pháp này có vẻ tốt hơn so với Jonnii, sử dụng năng suất có vẻ tự nhiên hơn khi giao dịch với enumerable –

0

IEnumerable được thiết kế để lặp qua các mặt hàng. Nó không luôn luôn có một bộ sưu tập như sự ủng hộ của nó. Ngoài ra, trong khi bạn đang lặp qua bộ sưu tập, bạn không thể sửa đổi bộ sưu tập.

Nếu bạn cần cập nhật bộ sưu tập của mình trong khi lặp lại nó, bạn cần tạo bản sao trước khi bắt đầu vòng lặp foreach của mình. Phương pháp ToList() của LINQ là một cách hay để thực hiện điều này.

0

Có thể không phải là câu trả lời bạn đang tìm kiếm, nhưng việc sử dụng các lớp sưu tập chung chung dường như luôn giải quyết được các loại vấn đề này đối với tôi. Hầu hết trong số họ có một phương thức .Add (T).

2

IEnumerable là bộ sưu tập chỉ đọc, ICollection cung cấp bộ sưu tập có thể thay đổi bằng Thêm và Xóa.

Tuy nhiên bạn có thể tạo một IEnumerable mới chứa tất cả các mục trong IEnumerable gốc và một mục mới, bằng cách kết hợp 2 danh sách:

var newCollection = original.Concat(new[]{element}); 
6

tôi muốn chỉ ra một số các câu trả lời khác ở đây IEnumerable không phải là một bộ sưu tập chỉ đọc, Nó không phải là một bộ sưu tập nào cả. Nó là một giao diện xác định cách một bộ sưu tập có thể được lặp lại.

Nếu bạn muốn thêm đối tượng, bạn nên thêm đối tượng vào lớp thu gom cụ thể hoặc ít nhất bằng cách sử dụng giao diện khác.

4

Lưu ý những gì người khác đã nói về việc không thực sự có thể "thêm" vào số đếm được, bạn vẫn có thể mô phỏng việc thêm. Trong thực tế, tôi cho rằng bạn có thể "thêm" một mục vào một chuỗi bằng cách biến đổi chuỗi thành chuỗi mới thực tế "chứa" mục (chỉ lặp lại chuỗi mới nếu bạn không tin tôi!) .

Bạn cũng có thể thể hiện một mặt hàng duy nhất là một cái gì đó đếm được như thế này:

//ToEnumerable might not be the best name here 
public static IEnumerable<T> ToEnumerable<T>(this T item) 
{ 
    return Enumerable.Repeat(item,1); 
} 

hoặc

public static IEnumerable<T> ToEnumerable<T>(this T item) 
{ 
    yield return item; 
} 

Sau đó, bạn có thể "thêm" một mục để một đếm được như thế này:

var items = GetSomeItems(); 

var itemsWithNewItemOnEnd = items.Concat(somenewitem.ToEnumerable()); 

var itemsWithNewItemAtStart = somenewitem.ToEnumerable().Concat(items); 

Bạn thậm chí có thể chèn mục vào một số vị trí khác theo thứ tự như thế này (giả sử bạn biết vị trí mà sau đó bạn muốn chèn nó):

var itemsWithNewItemInserted = items.Take(5).Concat(somenewitem.ToEnumerable()).Concat(items.Skip(5)); 

Sau khi bạn hoàn tất thao tác của mình (tức là bạn đã thao tác chuỗi của bạn để nó "chứa" những gì bạn muốn chứa), có thể bạn sẽ muốn làm cho một mảng hoặc danh sách ra khỏi chuỗi qua các phương pháp ToArray hoặc ToList:

var itemsWithNewItemInserted = items.Take(5).Concat(somenewitem.ToEnumerable()).Concat(items.Skip(5)).ToList(); 

Bây giờ itemsWithNewItemInserted là một danh sách chứa tất cả các mục mong muốn từ danh sách gốc, với các mục mới được chèn vào ở giữa.

Đánh lừa xung quanh với các chuỗi quá nhiều như thế này (lấy, bỏ qua, chèn, v.v.) có thể khiến bạn mất thời gian vì mỗi phương pháp mở rộng thêm (Take, Skip, v.v.) có thể khiến chuỗi được lặp lại nhiều lần, nhưng cú pháp hiểu danh sách làm cho nó dễ dàng hơn để thể hiện các hoạt động có vẻ khá phức tạp hơn bằng cách sử dụng lặp lại thông thường.

Ngoài ra, đây là một số liên kết thảo luận bày tỏ mục duy nhất là IEnumerable:

Passing a single item as IEnumerable<T>

Is there a neater linq way to 'Union' a single item?

+0

Tôi nghĩ ToEnumerable (với Concat) là giải pháp gọn gàng nhất. –

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