2012-04-24 14 views
44

Niedawno zacząłem robić zakupy w Windows 8 i odkryłem, że jeden z moich starych kumpli zaginął.Czy została usunięta lista dla metody <T> .ForEach()?

Używam raczej metody .ForEach() niż tradycyjnej konstrukcji foreach() i szybko zdałem sobie sprawę, że ta metoda nie jest dostępna. Na przykład, ten kod nie zostanie skompilowany pod metro app:

var list = new List<string>(); 

list.ForEach(System.Diagnostics.Debug.WriteLine); 

Rozglądałem się, aby zobaczyć, czy mogę znaleźć żadnej dyskusji o tym, ale nie był w stanie. Czy jestem po prostu tępy, czy faktycznie go nie ma?

+3

IEnumerable nigdy nie miał metodę rozszerzenia ForEach tylko IList ma go – Clueless

+0

Ty panie, są prawidłowe. Byłem przedwcześnie generyczny. Zmienię tytuł pytania. – Robaticus

+0

Zrobiłem ten sam błąd - tytuł mówi, że jest niezliczony, ale przykład wyraźnie próbuje go na liście. Edycja: Tytuł zaktualizowany :-) – yamen

Odpowiedz

42

It's indeed gone:

Lista <T> .ForEach została usunięta w stylu Metro aplikacji. Chociaż metoda wydaje się prosta, ma wiele potencjalnych problemów, gdy lista zostaje zmutowana przez metodę przekazaną do ForEach. Zamiast tego zaleca się po prostu użyć pętli foreach.


Wes Haggard | Zespół .NET Framework (BCL) | http://blogs.msdn.com/b/bclteam/

Bardzo dziwnie, jednak sprawia, że ​​pojawienie się w documentation, w którym nigdzie nie zawiera oświadczenie, że metoda ta nie jest obsługiwana w .NET dla systemu Windows Store aplikacji (dawniej .NET dla aplikacji Metro-styl) . Być może jest to tylko niedopatrzenie części zespołu dokumentacyjnego.

+1

@Robaticus: Możesz po prostu dodać własną metodę rozszerzenia, aby ją zastąpić. Prawdopodobnie najlepiej byłoby najpierw wywołać '.ToList()', następnie iterować to. Nic takiego jak iterowanie źródła podczas próby zmutowania go, by zrujnować twój dzień. – Will

+1

@Will - Zgadzam się, że mogę to zrobić. To chyba dobry zwyczaj, aby się wydostać, szczególnie, gdy pokazuje się nowym programistom LINQ, jak robić rzeczy. – Robaticus

16

Alternatywą jest go zdefiniować siebie przedmiotu:

public static IEnumerable<T> ForEach<T>(this IEnumerable<T> enumeration, Action<T> action) 
{ 
    foreach(T item in enumeration) 
    { 
     action(item); 
     yield return item; 
    } 
} 

kredytowe: LINQ equivalent of foreach for IEnumerable<T>

(Uwaga: nie duplikat)

+2

Chociaż jest to z pewnością akceptowalna praktyka, należy uważać, aby nie modyfikować żadnych wymagań poprzednich połączeń IEnumerable (takich jak Where lub OrderBy). Ponadto, jeśli chcesz kontynuować łańcuch połączeń IEnumerable, możesz zmienić typ zwracania na 'IEnumerable ' i 'return return item' po wykonaniu akcji na elemencie. Jednak będzie to nadal mutować elementy, więc należy pamiętać, że te "skutki uboczne" mogą zmienić wyliczenie. – SPFiredrake

+0

Tak, ForEach jest z pewnością niebezpieczny. Zaktualizowałem odpowiedź, aby zwrócić 'IEnumerable ' w celu umożliwienia ciągłego łączenia, ale najprawdopodobniej spowoduje to, że rzeczy staną się bardziej niebezpieczne. – yamen

18

Aby zorientować się, dlaczego to może nie być włączone, przeczytaj ten post przez kogoś, kto pracuje w zespole C# w Microsoft: http://blogs.msdn.com/b/ericlippert/archive/2009/05/18/foreach-vs-foreach.aspx

Zasadniczo jest to filozofia. Funkcje "LINQ" są bardzo inspirowane paradygmatem programowania funkcjonalnego, a rozszerzenie ForEach leci w obliczu tego ... zachęca do złego stylu funkcjonalnego.

+0

Joel: Dostałem przedwcześnie ogólne i zmieniono tytuł, aby odzwierciedlić listę , zamiast IEnumerable . – Robaticus

+8

"Ktoś, kto pracuje w zespole C# w Microsoft" Jak subtelny ... – BoltClock

+9

Ahhh, to znowu ten facet Lipperta. Co on, do cholery, wie? ;) – Robaticus

Powiązane problemy