Я так понимаю, вопрос про то, что для прохода по коллекции через foreach совершенно не обязательно реализовывать IEnumerable - достаточно написать пару методов:
public class MyEnumerable {
public MyEnumerator GetEnumerator() => new MyEnumerator();
}
public class MyEnumerator {
// Этот метод должен переходить к следующему элементу, и возвращать true, если переход произошёл,
// и false, если дальше элементов нет
public bool MoveNext() => false;
// Это свойство должно возвращать текущий элемент
public int Current => 0;
}
Тогда можно будет засунуть это в форич:
foreach(int x in new MyEnumerable()) {
Console.WriteLine(x); // вообще-то мы сюда не попадём, тк Next всегда возвращает false, но синтаксической ошибки нет.
}
Изначально это было придумано для того, чтобы не вызывать лишний боксинг элементов при итерации по массивам, тк изначально в С# не было обобщений => не было обобщённого IEnumerable<T>
Но сейчас этим имеет смысл пользоваться только тогда, когда ты хочешь проитерироваться по ref struct, тк они не могут реализовывать интерфейсы.