Concise code to perform action on every element, when need index When I read this answer, which has code:

linqObject.Where((obj, index) =&gt; {
  DoWork(obj, index);
  return true;
}).ToArray(); //MUST CALL ToArray() or ToList() or something to execute the lazy query, or the loop won't actually execute


My initial reaction was similar to Mark Sowul's comment:


  "Wastes memory (allocating a list or array) and risks bugs (if you don't call ToList or ToArray). Why?".




But on further thought, what is a concise approach, avoiding the downsides of the above?
My first attempt:

int index = 0;
foreach (var item in someEnumerable) {
    DoWork(item, index);
    index++;
}


Compared to calling a Linq operator, that seems verbose, low-level. I'm defining and manipulating an index, whereas Linq has an Operator that "almost" does what I want - takes care of the index tracking for me.

Personally, I would write the explicit foreach loop - but maybe that is only because I've been programming a long time, and am comfortable with that syntax.



Is there a more concise solution, that doesn't have the downsides of the first version shown (Where / ToArray)?

I'm trying to get comfortable with encapsulating such stuff into methods, often by using Action&lt;&gt; or Func&lt;&gt;, which are newer [to me] than the style of programming that became my habit. So that instead of repeating similar snippets of code, I just call a method.


  As an aside, Linq is also newer than my habits. Linq is concise, but not in a way that I find helpful; I find loops clearer to read; a better separation of the aspects of what is happening. But I'm open to seeing situations where its expressive power is appropriate.
  [OFF-TOPIC: In contrast, I spent some time with F#, and found it to be fantastic. I LOVE the combination of functional with OO; just not the way Linq jams a handful of functional constructs into C#'s syntax. But this question is about making good use of C#, so all advice is appreciated.]


I think this becomes:

public static void ForEachWithIndex&lt;T&gt;(IEnumerable&lt;T&gt; e, Action&lt;int, T&gt; a)
{
    int index = 0;
    foreach (T v in e) {
        a(index, v);
        index++;
    }
}


which might be used like this:

ForEachWithIndex(e, (int index, T item) =&gt; {
    // Do Work based on index and item.
});


Or if an appropriate "DoWork" method already exists, simply:

ForEachWithIndex(e, DoWork);


Comments?  Improvements, or alternatives?
Is there a way to use Linq more concisely/efficiently than in the original code sample?



NOTE: I did not make this an "extension method" on "IEnumerable", due to comments people made in stackoverflow threads regarding "ForEach" as a possible extension method: dislike of a syntax that looks similar to a Linq operator - which traditionally don't have side-effects - for a method that clearly DOES have side-effects; indeed is all about the side-effects.
linqObject.Where((obj, index) =&gt; {
  DoWork(obj, index);
  return true;
}).ToArray();



Never ever! This is the worst possible abuse of an API. I 100% agree with the comment.




int index = 0;
foreach (var item in someEnumerable) {
    DoWork(item, index);
    index++;
}



Yes, this is the way it should be, although this can be shortened... keep reading.




public static void ForEachWithIndex&lt;T&gt;(IEnumerable&lt;T&gt; e, Action&lt;int, T&gt; a)
{
    int index = 0;
    foreach (T v in e) {
        a(index, v);
        index++;
    }
}



This is better but the naming is still quite wrong and the Action parameters are in the wrong order. They should be incremental. This means that T is always there so it should be first, then any other parameters may follow, like the index.



I'm not sure what's wrong with using normal loops where necessary but if you really want to encapsulate them then...



Try to be consistant with the LINQ API and don't invent new method suffixes like WithIndex. Use overloads instead. In fact you can implement it once and call the core method with other overloads.

Notice the order of Action parameters. It's consistant with current APIs. T first then index. There is also no explicit parameter checking because it uses an empty collection if the source is null and the ? operator to not call the delegate if this one is null. You can also throw if you want.

public static class Loop
{
    public static void ForEach&lt;T&gt;(IEnumerable&lt;T&gt; source, Action&lt;T, int&gt; action)
    {
        var i = 0;
        foreach (var item in source ?? Enumerable.Empty&lt;T&gt;()) action?.Invoke(item, i++);
    }

    public static void ForEach&lt;T&gt;(IEnumerable&lt;T&gt; source, Action&lt;T&gt; action)
    {
        ForEach(source, (x, i) =&gt; action(x));
    }
}