2010-11-15 10 views

Odpowiedz

23

Naprawdę nie można dodać elementy IEnumerable jak to ma być tylko do odczytu. Najprościej jest albo coś takiego:

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

lub

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

Można łączyć je z singleton tablicy:

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

Punktem IEnumerable jest to, że jest to tylko do odczytu kolekcja styl ciągnąć. Jeśli chcesz, możesz symulować dodatek robiąc coś takiego:

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

    yield return additionalItem; 
} 
+2

Pokornie sugeruję nazywanie tej metody "Concat", ponieważ uważam, że przekazuje ona intencję metoda lepsza niż "Dodaj", która ma bardzo silne znaczenie w przypadku kolekcjonowania s. – GuiSim

+3

'Append' jest jeszcze lepszy. Concat ma ochotę połączyć się z czymś podobnym, podczas gdy Add/Append czuje się jak uzupełnianie czegoś (choć Add czuje się mniej leniwie). – nawfal

+0

W jakiś sposób ta metoda wydaje się lepsza niż Jonnii, użycie plonu wydaje się bardziej naturalne, gdy mamy do czynienia z przeliczalnym –

0

IEnumerable przeznaczony jest iteracyjne nad elementów. Nie zawsze ma kolekcję jako wsparcie. Ponadto podczas przechodzenia przez kolekcję nie można modyfikować kolekcji.

Jeśli chcesz zaktualizować kolekcję podczas iteracji, musisz wykonać kopię przed uruchomieniem pętli foreach. Metoda LINQ'a ToList() jest dobrym sposobem na zrobienie tego.

0

Może nie jest to odpowiedź, której szukasz, ale korzystanie z ogólnych klas kolekcji zawsze wydaje się rozwiązywać tego typu problemy. Większość z nich ma metodę .Add (T).

2

IEnumerable jest kolekcją tylko do odczytu, ICollection udostępnia zmienną kolekcję z Add and Remove.

Jednak można utworzyć nowy IEnumerable zawierać wszystkie elementy w oryginale IEnumerable i na nowej pozycji, przez złączenie 2 list:

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

chciałbym wskazać kilka innych odpowiedzi tutaj że IEnumerable nie jest kolekcją tylko do odczytu, to wcale nie jest kolekcja. Jest to interfejs definiujący sposób, w jaki kolekcja może być iterowana.

Jeśli chcesz dodawać obiekty, powinieneś dodawać obiekty do konkretnej klasy kolekcji lub przynajmniej używać innego interfejsu.

4

Pamiętając o tym, co inni powiedzieli o braku możliwości "dodania" do liczby mnogiej, można nadal symulować dodawanie. W rzeczywistości, argumentowałbym, że możesz "dodać" element do sekwencji, zmieniając kolejność w nową sekwencję, która faktycznie "zawiera" przedmiot (po prostu powtarzaj nową sekwencję, jeśli mi nie wierzysz!) .

Można również wyrazić pojedynczy element jako przeliczalnego coś takiego:

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

lub

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

Następnie można „dodać” element do przeliczalny tak:

var items = GetSomeItems(); 

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

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

Można nawet wstawić element do innej lokalizacji w takiej kolejności (zakładając, że wiesz pozycja, po której chcesz go wstawić):

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

Po zakończeniu operacji (tj. masz manipulować swoją sekwencję tak, że „zawiera”, co chcesz zawierać), prawdopodobnie będziesz chciał zrobić tablicę lub listę Spośród sekwencji za pomocą metod ToArray lub ToList:

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

Teraz itemsWithNewItemInserted jest lista zawierająca wszystkie żądane elementy z oryginalnej listy, z nowymi elementami wstawionymi w środku.

Używanie zbyt dużych sekwencji (pobieranie, pomijanie, wstawianie itp.) Może kosztować cię z czasem, ponieważ każda dodana metoda rozszerzenia (Take, Skip, itp.) Może wielokrotnie powtarzać sekwencję, ale Składnia ze zrozumieniem listy ułatwia wyrażanie operacji, które wydają się być nieco bardziej zawiłe przy użyciu konwencjonalnej iteracji.

oto kilka linków, które omawiają wyrażania pojedynczych elementów jak IEnumerable:

Passing a single item as IEnumerable<T>

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

+0

Myślę, że ToEnumerable (z Concat) to najmodniejsze rozwiązanie. –

Powiązane problemy