Skip to content

Instantly share code, notes, and snippets.

@sunmeat
Created October 7, 2025 11:49
Show Gist options
  • Save sunmeat/51ff51bf73700b86f22bc5003cbd684b to your computer and use it in GitHub Desktop.
Save sunmeat/51ff51bf73700b86f22bc5003cbd684b to your computer and use it in GitHub Desktop.
явна реалізація IEnumerable та IEnumerator
using System.Collections;
using System.Text;
namespace EnumerableDemo
{
class Program
{
static void Main()
{
Console.OutputEncoding = Encoding.UTF8;
var collection = new MonsterCollection();
// foreach - це синтаксичний цукор
Console.WriteLine("Перебирання через foreach:");
foreach (var item in collection)
{
Console.Write(item + " ");
}
Console.WriteLine();
// ручне перебирання через перелічувач
Console.WriteLine("Ручне перебирання:");
for (var tmp = (MonsterEnumerator?)collection.GetEnumerator(); tmp.MoveNext();)
{
var item = tmp?.Current;
Console.Write(item + " ");
}
Console.WriteLine();
}
}
class Monster
{
public int Health { get; set; }
public string Name { get; set; }
public Monster(int health, string name)
{
Health = health;
Name = name;
}
public override string ToString()
{
return $"{Name}: {Health}";
}
}
// клас-колекція: надає клієнту можливість переглянути всі елементи колекції за допомогою foreach
class MonsterCollection : IEnumerable<Monster?> // явно реалізуємо інтерфейс IEnumerable<T>
{
// зазвичай у такому класі присутнє інкапсульоване поле-колекція з будь-якою кількістю елементів та будь-якими типами
private Monster[] monsters = new Monster[3];
// List<Monster> monsters = new List<Monster>();
public MonsterCollection()
{
monsters[0] = new Monster(10, "Кликан");
monsters[1] = new Monster(20, "Зубан");
monsters[2] = new Monster(30, "Хвостан");
}
// при бажанні, можна буде дописати методи Add, Remove, Clear, Count, Search ...
// у класі-колекції повинен бути публічний метод GetEnumerator без параметрів
public IEnumerator<Monster?> GetEnumerator()
{
// з цього методу потрібно повернути посилання на об'єкт-перелічувач колекції
return new MonsterEnumerator(monsters); // зазвичай у конструктор при створенні об'єкта-перелічувача відправляється посилання на колекцію даних
}
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); // неузагальнений варіант (для повної сумісності з legacy-кодом, наприклад, методами, які приймають IEnumerable без <T>, потрібно реалізувати обидві версії)
}
// окремий клас, який описує алгоритм перелічення елементів
class MonsterEnumerator : IEnumerator<Monster?>
{
// ще одне посилання на колекцію (але вже для перелічувача)
private Monster[]? monsters = null;
// явний конструктор для отримання посилання на колекцію
public MonsterEnumerator(Monster[]? monsters)
{
this.monsters = monsters; // запам'ятали посилання на колекцію
index = -1; // початковий стан перед першим викликом MoveNext
}
// у класі-перелічувачі обов'язково повинно бути свойство Current (посилання на наступний необроблений об'єкт)
public Monster? Current
{
get;
private set; // зазвичай секція set закрита (бо для стандартних колекцій через цю властивість не можна змінювати значення елементів колекції)
// класично, foreach - це цикл на перегляд (читання) елементів
}
object? IEnumerator.Current => Current;
// у класі можуть бути додаткові поля (щоб не загубитися в процесі огляду колекції)
private int index = 0;
// у класі-перелічувачі обов'язково повинен бути метод MoveNext
// він перевіряє, чи є взагалі елементи в колекції, якщо їх спочатку немає - повертає false (умова виходу з foreach)
// також перевіряє, чи залишилися необроблені елементи - якщо все переглянули - повертається false (у колекції більше нічого робити)
// якщо необроблені елементи ще є - виставляється посилання (через Current) на наступний елемент, і повертається true
public bool MoveNext()
{
if (monsters?.Length == 0 || index >= monsters?.Length - 1)
return false;
Current = monsters?[++index];
return true;
}
// скидає перелічувач на початок
public void Reset()
{
index = -1;
}
// звільняє ресурси (для простоти прикладу - порожній)
public void Dispose() { }
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment