0

I changed a collection from List to Dictionary and it seems I need change from using .ForEach() to foreach() on it - regardless if I'm iterating the Dictionary itself, or Dictionary.Values.

It's no big deal but I've seen a few times slight discrepancies when you can and can't use LINQ, and I wondered if there is a way and I just missed it?

Mr. Boy
  • 60,845
  • 93
  • 320
  • 589
  • 2
    A dictionary is enumerable so all you have to do is do dict.Select() or dict.Where() – jdweng May 15 '20 at 17:27
  • 3
    `.ForEach` is actually a [method on](https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.list-1.foreach?view=netcore-3.1) `List` not `IEnumerable` hence why its not working for `Dictionary` and not in Linq. – peinearydevelopment May 15 '20 at 17:33
  • Also see question here: https://stackoverflow.com/questions/101265/why-there-is-no-foreach-extension-method-on-ienumerable – peinearydevelopment May 15 '20 at 17:35
  • Yeah I wondered what `Values` is... I thought that might ultimately be a `List` but apparently not. I wonder if there's a good technical reason or just 'because'? – Mr. Boy May 15 '20 at 17:38
  • Further reading [“foreach” vs “ForEach”](https://learn.microsoft.com/en-us/archive/blogs/ericlippert/foreach-vs-foreach) – Pavel Anikhouski May 15 '20 at 17:39
  • That's interesting @PavelAnikhouski though one could surely make the same argument that `.ForEach` is fairly pointless for the same reasons. Anyway thanks for the link, – Mr. Boy May 15 '20 at 17:53
  • 2
    @Mr.Boy LINQ is declarative methods that don't modify source collection but rather filter/map in *a lazy way*. ForEach is is somewhat opposite of it... Indeed `Select(x => action(x)).All()` is rough equivalent of `.ForEach` but that's really confusing and regular `foreach` would be more self-documneting if you need non-lazy execution. – Alexei Levenkov May 15 '20 at 18:05
  • Is this asking about the `ForEach()` method specifically, or "`ForEach()` or similar/equivalent" (i.e. `foreach` and LINQ)? If the former, `List<>.ForEach()` can't be called on another class, of course. If the latter, I think that is a well-covered question already. See also: [`Dictionary.ForEach`](https://stackoverflow.com/q/34416931/150605) method, [`Dictionary ForAll / ForEach method`](https://stackoverflow.com/q/46229829/150605), [`Why does the generic Dictionary in .NET not provide a ForEach() method`](https://stackoverflow.com/q/46229829/150605)? – Lance U. Matthews May 15 '20 at 20:06
  • Using a Select enumerates through the dictionary. A dctionary is a List>. When using Select each object is KeyValuePair. – jdweng May 18 '20 at 10:54
  • @AlexeiLevenkov OK that clarifies a bit further. Thanks. – Mr. Boy May 18 '20 at 11:46

1 Answers1

2

Unfortunately .ForEach() is only defined on the List<> class.

You could either use .ToList() first to get access to .ForEach but that will, of course, lower the performance compared to just using foreach or you could create extension-methods for that:

public static void ForEach<T, U>(this Dictionary<T, U> d, Action<KeyValuePair<T, U>> a)
{
    foreach (KeyValuePair<T, U> p in d) { a(p); }
}

public static void ForEach<T, U>(this Dictionary<T, U>.KeyCollection k, Action<T> a)
{
    foreach (T t in k) { a(t); }
}

public static void ForEach<T, U>(this Dictionary<T, U>.ValueCollection v, Action<U> a)
{
    foreach (U u in v) { a(u); }
}

If you are interested in further information, there is already a similar article on SO.

oRole
  • 1,316
  • 1
  • 8
  • 24