foreach with generic List, detecting first iteration when using value type

foreach(int i in ints.Take(1))
{
 //do first thing
}

foreach(int i in ints.Skip(1))
{
  //do other things
}

A while ago I wrote SmartEnumerable (part of MiscUtil) which lets you know if the current element is the first or last, as well as its index. That may help you... it's part of MiscUtil, which is open source - you can take just SmartEnumerable under the same licence, of course.

Sample code (c'n'p from the web page):

using System;
using System.Collections.Generic;

using MiscUtil.Collections;

class Example
{
    static void Main(string[] args)
    {
        List<string> list = new List<string>();
        list.Add("a");
        list.Add("b");
        list.Add("c");
        list.Add("d");
        list.Add("e");

        foreach (SmartEnumerable<string>.Entry entry in
                 new SmartEnumerable<string>(list))
        {
            Console.WriteLine ("{0,-7} {1} ({2}) {3}",
                               entry.IsLast  ? "Last ->" : "",
                               entry.Value,
                               entry.Index,
                               entry.IsFirst ? "<- First" : "");
        }
    }
}

EDIT: Note that while it works with reference types with distinct references, it'll still fail if you give it a list where the first reference crops up elsewhere in the list.


Well, you could code it using explicit iteration:

using(var iter = ints.GetEnumerator()) {
  if(iter.MoveNext()) {
     // do "first" with iter.Current

     while(iter.MoveNext()) {
       // do something with the rest of the data with iter.Current
     }
  }
}

The bool flag option (with foreach) is probably easier though... that is what I (almost) always do!

Another option would be LINQ:

if(ints.Any()) {
  var first = ints.First();
  // do something with first
}

foreach(var item in ints.Skip(1)) {
  // do something with the rest of them
}

The downside of the above is that it tries to look at the list 3 times... since we know it is a list, that is fine - but if all we had was an IEnumerable<T>, it would only be sensible to iterate it once (since the source might not be re-readable).

Tags:

C#

.Net