В чём разница между этими интерфейсами и в каких случаях нужно использовать один, а в каких - другой?
По сути и один и другой предоставляет простой перебор по коллекции. Но различие между ними всё-же есть.
Интерфейс IEnumerable имеет метод, возвращающий ссылку на интерфейс IEnumerator, а именно на перечислитель, осуществляющий итерацию по коллекции. В IEnumerable мы имеем один единственный метод GetEnumerator.
Интерфейс IEnumerator определяет непосредственный перебор внутренних объектов в контейнере, а именно методы :
1) bool MoveNext(); - перемещение в контейнере на одну позицию вперёд
2) object Current { get; } - возвращает текущий элемент в контейнере
3) void Reset(); - перемещение в начало контейнера.