Al programmatore le collezioni servono sempre per essere enumerate. E per farlo semplicemente da sempre si utilizzano strategie per utilizzare enumeratori standard piuttosto che conoscere puntulamente l'implementazione della classe collezione di riferimento.

Requisiti
Una collection per essere enumerabile deve implementare l'interfaccia IEnumerable (o la sua versione generic IEnumerable<T>) ed esporre il metodo:

IEnumerator GetEnumerator();

che dovrà tornare un oggetto che implementa l'interfaccia IEnumerator.
A sua volta, la classe in questione dovrà esporre i metodi/proprietà:
object Current { get; }
bool MoveNext();
void Reset();

Nota: siccome l'enumerazione va in avanti, il metodo Reset porta l'enumerazione all'inizio.
Utilizzo esplicito di un enumeratore:
List<string> messaggi=new List<string>();
IEnumerator<string> en = messaggi.GetEnumerator();
while (en.MoveNext())
{
    Console.WriteLine(en.Current);
}

Questo meccanismo può essere semplificato dall'utilizzo del costrutto foreach, che altro non fa che fare esattamente ciò che abbiamo appena scritto, solo risparmiando al developer un pò di tempo:
List<string> messaggi=new List<string>();
foreach (var item in messaggi)
{
    Console.WriteLine(item);
}

Iteratori e istruzione yield
L'iteratore è un enumeratore generato dal compilatore. Molti esempi possono portare confusione perciò partiamo da un problema matematico: come creare la collection "tutti i numeri naturali"? A primo sguardo uno potrebbe dire "impossibile, non è decidibile come problema". Infatti, è vero: tuttavia possiamo definire una collection (solamente definirla) e poi lasciare che venga di fatto costruita in fase di runtime.

static IEnumerable<int> GetNaturals()
{
    int i = 0;
    while (true)
    {
        yield return i;
        i++;
    }
}

la funzione (non fate caso sia statica) mi restituisce una collection di tutti i numeri naturali MA lì creerà solo al momento della richiesta, cioè qui:
static void Main(string[] args)
{
    foreach (var item in GetNaturals())
    {
        Console.WriteLine(item);
    }
}

Potente!