locked
Linq Foreach on SortedList and Dictionary? RRS feed

  • Question

  • Hi,

    Why isn't there a "Foreach" linq extension to a SortedList? For example I can do this:

    foreach (var keyValuePair in mySortedList)
       Console.WriteLine(keyValuePair.Key);

    But I can't do like this:

    mySortedList.Foreach(x=>Console.WriteLine(x.Key));

    Why not? And does anyone have an extension that does this?

    --
    Werner

    Friday, April 1, 2011 8:20 AM

Answers

  • Microsft has responsed to this question (or rather why IEnumerable<T> doesn't have a ForEach method) on numerous occasions and the primary reason is, that it isn't a nice thing from a functional programming perspective. Foreach could result in side effects on the original list being iterated, and that is not done. In a functional programming world that is.

    From a more iterative perspective you could argue that ForEach makes perfect sense. That, and also because of guaranteed performance, was the reason to include the ForEach method on the List<T> class. The ForEach implementation is also a tiny bit faster than a normal foreach loop, because internally it uses a for (int i = 0; i<count; i++) loop instead of using an enumerator.

    You're more than welcome to write your own implementation of the ForEach extension method (it's a simple 3 liner containing a normal for (each) loop). Or you could use Parallel.For, which works on any IEnumerable.

    Or you could indeed call ToList, but that could have some performance implications, I'm not sure ToList is as efficient on every datasource, so I'd try to stay away from it when a simple for each loop would work just fine.

    Friday, April 1, 2011 11:26 AM
  • Eric Lippert shares his thoughts on this subject.

    Actually its very easy to add this kind of feature to your own
    libraries:

    public static class EnumerableExtensions
    {
      public static void ForEach<T> (this IEnumerable<T> enumerable, Action<T> action)
      {
       foreach (T item in enumerable) action.Invoke(item);
      }
      public static void ForEach (this IEnumerable enumerable, Action<object> action)
      {
       foreach (object item in enumerable) action.Invoke(item);
      }
    }
    

    Note that as for classes that expose a ForEach member, such as List<T>
    calls to list.ForEach will still call the the built-in method, not the extension.


    Christoph
    Friday, April 1, 2011 12:13 PM
  • hi,

    Untested, ToList() should work:

    mySortedList.ToList().ForEach(x=>Console.WriteLine(x.Key));
    
    


    Microsoft MVP Office Access
    https://mvp.support.microsoft.com/profile/Stefan.Hoffmann
    • Proposed as answer by Adavesh Friday, April 1, 2011 10:03 AM
    • Marked as answer by Werner Clausen Friday, April 1, 2011 9:38 PM
    Friday, April 1, 2011 9:06 AM

All replies

  • hi,

    Untested, ToList() should work:

    mySortedList.ToList().ForEach(x=>Console.WriteLine(x.Key));
    
    


    Microsoft MVP Office Access
    https://mvp.support.microsoft.com/profile/Stefan.Hoffmann
    • Proposed as answer by Adavesh Friday, April 1, 2011 10:03 AM
    • Marked as answer by Werner Clausen Friday, April 1, 2011 9:38 PM
    Friday, April 1, 2011 9:06 AM
  • Microsft has responsed to this question (or rather why IEnumerable<T> doesn't have a ForEach method) on numerous occasions and the primary reason is, that it isn't a nice thing from a functional programming perspective. Foreach could result in side effects on the original list being iterated, and that is not done. In a functional programming world that is.

    From a more iterative perspective you could argue that ForEach makes perfect sense. That, and also because of guaranteed performance, was the reason to include the ForEach method on the List<T> class. The ForEach implementation is also a tiny bit faster than a normal foreach loop, because internally it uses a for (int i = 0; i<count; i++) loop instead of using an enumerator.

    You're more than welcome to write your own implementation of the ForEach extension method (it's a simple 3 liner containing a normal for (each) loop). Or you could use Parallel.For, which works on any IEnumerable.

    Or you could indeed call ToList, but that could have some performance implications, I'm not sure ToList is as efficient on every datasource, so I'd try to stay away from it when a simple for each loop would work just fine.

    Friday, April 1, 2011 11:26 AM
  • Eric Lippert shares his thoughts on this subject.

    Actually its very easy to add this kind of feature to your own
    libraries:

    public static class EnumerableExtensions
    {
      public static void ForEach<T> (this IEnumerable<T> enumerable, Action<T> action)
      {
       foreach (T item in enumerable) action.Invoke(item);
      }
      public static void ForEach (this IEnumerable enumerable, Action<object> action)
      {
       foreach (object item in enumerable) action.Invoke(item);
      }
    }
    

    Note that as for classes that expose a ForEach member, such as List<T>
    calls to list.ForEach will still call the the built-in method, not the extension.


    Christoph
    Friday, April 1, 2011 12:13 PM
  • public static class EnumerableExtensions
    
    {
      public void ForEach<T> (this IEnumerable<T> enumerable, Action<T> action)
    
      {
    
       foreach (T item in enumerable) action.Invoke(item);
      }
    
      public void ForEach (this IEnumerable enumerable, Action<object> action)
    
      {
    
       foreach (object item in enumerable) action.Invoke(item);
    
      }
    
    }
    
    


    Could you show a sample implementation of this extension?

     

    Friday, April 1, 2011 4:10 PM
  • Microsft has responsed to this question (or rather why IEnumerable<T> doesn't have a ForEach method) on numerous occasions and the primary reason is, that it isn't a nice thing from a functional programming perspective. Foreach could result in side effects on the original list being iterated, and that is not done. In a functional programming world that is.

    From a more iterative perspective you could argue that ForEach makes perfect sense. That, and also because of guaranteed performance, was the reason to include the ForEach method on the List<T> class. The ForEach implementation is also a tiny bit faster than a normal foreach loop, because internally it uses a for (int i = 0; i<count; i++) loop instead of using an enumerator.

    You're more than welcome to write your own implementation of the ForEach extension method (it's a simple 3 liner containing a normal for (each) loop). Or you could use Parallel.For, which works on any IEnumerable.

    Or you could indeed call ToList, but that could have some performance implications, I'm not sure ToList is as efficient on every datasource, so I'd try to stay away from it when a simple for each loop would work just fine.

    Excellent and informative answer. Many thanks :)

    Oh, and also thanks to the other answers, very helpful all!

    -- 
    Werner 

    Friday, April 1, 2011 9:41 PM
  • Actually the code posted already is the implementation.
    As for a usage sample:


       
      using System;
      using System.Collections.Generic;
      using System.Collections.ObjectModel;
    
      public class Program
      {
        static void Main()
        {
          Collection<double> purchasePrices = new Collection<double> {1000, 2000, 3000, 4000};
          Collection<double> salesPrices = new Collection<double>();
    
          const double VAT = 1.19;
    
          purchasePrices.ForEach(pp => salesPrices.Add(pp * VAT));
          salesPrices.ForEach(sp => Console.WriteLine("{0:F2}", sp));
    
          Console.ReadKey(true);
        }
      }
    
      public static class EnumerableExtensions
      {
        public static void ForEach<T>(this IEnumerable<T> enumerable, Action<T> action)
        {
          foreach (T item in enumerable) action.Invoke(item);
        }
      }
    




    Friday, April 1, 2011 10:22 PM
  • Hi All,

    Just as a little inspiration I thought I'd post what my class ended up as (yes, I decided to implement it :)):

    /// <summary>
    /// IEnumerable Extensions
    /// </summary>
    public static class IEnumerableExtensions
    {
      /// <summary>
      /// Performs the specified action on each element of the IEnumerable<KeyValuePair<TKey, TValue>>.
      /// </summary>
      /// <typeparam name="TKey">The type of the key.</typeparam>
      /// <typeparam name="TValue">The type of the value.</typeparam>
      /// <param name="enumerable">The enumerable.</param>
      /// <param name="action">The action.</param>
      public static void ForEach<TKey, TValue>(this IEnumerable<KeyValuePair<TKey, TValue>> enumerable, Action<KeyValuePair<TKey, TValue>> action)
      {
        if (enumerable == null)
          throw new ArgumentNullException("enumerable");
    
        if (action == null)
          throw new ArgumentNullException("action");
    
        foreach (KeyValuePair<TKey, TValue> item in enumerable) action.Invoke(item);
      }
    }

    --

    Monday, April 4, 2011 3:04 PM