Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>You can achieve most of this with an extension method, and overloads of <code>Enumerable.Select</code> and <code>Where</code>.</p> <p>Both <code>Select</code> and <code>Where</code> have overloads where the delegate is passed both the item and its index:</p> <pre><code>var input = new[]{'a','b','c','d'}; var indexed = input.Select((v,i) =&gt; new { Value = v, Index = i }); foreach (var v in indexed) { Console.WriteLine("Index #{0} is '{1}'", v.Index, v.Value); } </code></pre> <p>To trigger delegates before the first and after the last items (but only if there is at least one item):</p> <pre><code>public static IEnumerable&lt;T&gt; StartAndEnd&lt;T&gt;(this IEnumerable&lt;T&gt; input, Action onFirst, Action onLast) { var e = input.GetEnumerator(); if (!e.MoveNext()) { yield break; } onFirst(); do { yield return e.Current; } while (e.MoveNext()); onLast(); } </code></pre> <p>and then use it as:</p> <pre><code>var input = new[]{'a','b','c','d'}; var indexed = input.StartAndEnd(() =&gt; { Console.WriteLine("First!");}, () =&gt; { Console.WriteLine("Last!");}) .Select((v,i) =&gt; new { Value = v, Index = i }); foreach (var v in indexed) { Console.WriteLine("Index #{0} is '{1}'", v.Index, v.Value); } </code></pre> <p>which gives the result:</p> <pre> First! Index #0 is 'a' Index #1 is 'b' Index #2 is 'c' Index #3 is 'd' Last! </pre> <p>The delegates could set a local (by forming a closure) which is checked in a loop.</p> <p>A more sophisticated version could call the onLast delegate before the last element of the sequence, but this would require buffering an element of the sequence to detect end before yielding that element.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload