๐Ÿ’ป Programming Language/C#

24. yield ํ‚ค์›Œ๋“œ

S.Honey 2022. 4. 7. 09:33
  • Enumerator(Iterator) : ์ง‘ํ•ฉ์ ์ธ ๋ฐ์ดํ„ฐ์…‹์œผ๋กœ๋ถ€ํ„ฐ ๋ฐ์ดํ„ฐ๋ฅผ ํ•˜๋‚˜์”ฉ ํ˜ธ์ถœ์ž์—๊ฒŒ ๋ณด๋‚ด์ฃผ๊ฒŒ ํ•˜๋Š” ๊ธฐ๋Šฅ => ๋ฐ˜๋ณต์ž

  • yield ํ‚ค์›Œ๋“œ๋Š” ํ˜ธ์ถœ์ž์—๊ฒŒ ์ปฌ๋ ‰์…˜ ๋ฐ์ดํ„ฐ๋ฅผ ํ•˜๋‚˜์”ฉ ๋ฆฌํ„ดํ•  ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ํ‚ค์›Œ๋“œ

  • yield ์‚ฌ์šฉ๋ฐฉ์‹

    • yield return : ์ปฌ๋ ‰์…˜ ๋ฐ์ดํ„ฐ๋ฅผ ํ•˜๋‚˜์”ฉ ๋ฆฌํ„ดํ•˜๋Š”๋ฐ ์‚ฌ์šฉ
    • yield break : ๋ฆฌํ„ด์„ ์ค‘์ง€ํ•˜๊ณ  Iteration ๋ฃจํ”„๋ฅผ ๋น ์ ธ๋‚˜์˜ฌ๋•Œ ์‚ฌ์šฉ

IEnumerator == ๋ฐ์ดํ„ฐ๋ฅผ ๋ฆฌํ„ด(Getter)ํ•˜๋Š” ์—ด๊ฑฐ์ž

public interface IEnumerator
{
    object Current { get; }
    bool MoveNext();
    void Reset();
}
  • Current
    • ์ฝ๊ธฐ ์ „์šฉ ํ”„๋กœํผํ‹ฐ๋กœ ํ˜„์žฌ ์œ„์น˜์˜ ๋ฐ์ดํ„ฐ๋ฅผ object ํƒ€์ž…์œผ๋กœ ๋ฆฌํ„ดํ•œ๋‹ค.
    • object๋Š” System.Object์™€ ๊ฐ™๋‹ค.
  • MoveNext (=> Java์˜ hasNext()์™€ ์œ ์‚ฌ)
    • ๋‹ค์Œ ์œ„์น˜๋กœ ์ด๋™ํ•˜๋Š”๋ฐ ๋‹ค์Œ ์œ„์น˜์— ๋ฐ์ดํ„ฐ๊ฐ€ ์žˆ์œผ๋ฉด true, ์—†์œผ๋ฉด false.
    • ๊ทธ๋ž˜์„œ ๋ณดํ†ต ์ปฌ๋ ‰์…˜ ์ธ๋ฑ์Šค๋ฅผ 1์”ฉ ์ฆ๊ฐ€ ์‹œ์ผœ ์ปฌ๋ ‰์…˜์˜ ๋์— ๋„๋‹ฌ ํ–ˆ๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” bool์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ์‹์œผ๋กœ ๊ตฌํ˜„ํ•จ.
  • Reset
    • ์ธ๋ฑ์Šค๋ฅผ ์ดˆ๊ธฐ ์œ„์น˜๋กœ ์ดˆ๊ธฐํ™”
    • ๋ณดํ†ต ์ปฌ๋ ‰์…˜์˜ ์ธ๋ฑ์Šค๋ฅผ -1๋กœ ์„ค์ •ํ•˜๋Š”์‹์œผ๋กœ ๊ตฌํ˜„
    • IEnumerator ๋ฅผ ๋ฆฌํ„ดํ•˜๋Š” ๋ชจ๋“  ํ•จ์ˆ˜๋Š” ref,out ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ํ—ˆ์šฉ๋˜์ง€ ์•Š๋Š”๋‹ค. ๋˜ํ•œ ๋žŒ๋‹ค ํ•จ์ˆ˜์— ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์—†๋‹ค.

IEnumerable == IEnumerator(์—ด๊ฑฐ์ž)๋ฅผ Getํ•˜๋Š”๋ฐ ํ•„์š”ํ•œ ์ธํ„ฐํŽ˜์ด์Šค

public interface IEnumerable
{
    IEnumerator GetEnumerator();
}
  • ๊ฐ์ฒด๋กœ foreach๋ฌธ์„ ๋Œ๋ฆฌ๊ธฐ ์œ„ํ•ด์„œ๋Š” ๊ทธ ๊ฐ์ฒด ํƒ€์ž…์ด IEnumerable์„ ์ƒ์†๋ฐ›์€ ํด๋ž˜์Šค์—ฌ์•ผ ํ•œ๋‹ค.

  • IEnumerable์„ ์ƒ์†๋ฐ›์•„ GetEnumerator()์„ ๊ตฌํ˜„ํ•œ ํด๋ž˜์Šค์ด์–ด์•ผ foreach๋กœ ๋‚ด๋ถ€ ๋ฐ์ดํ„ฐ๋ฅผ ์—ด๊ฑฐํ•  ์ˆ˜ ์žˆ๋‹ค.

  • ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ IEnumerable ๋ฅผ ๋ฆฌํ„ดํ•˜๋Š” ๋ชจ๋“  ํ•จ์ˆ˜๋Š” ref, out ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ํ—ˆ์šฉ๋˜์ง€ ์•Š๋Š”๋‹ค. ๋˜ํ•œ ๋žŒ๋‹ค ํ•จ์ˆ˜์— ์‚ฌ์šฉํ•  ์ˆ˜ ๋„ ์—†๋‹ค.


namespace yieldEx
{
    class Program
    {

        static IEnumerable<int> GetNumber()
        {
            yield return 1;
            yield return 2;
            yield return 3;
        }

        static void Main(string[] args)
        {
            foreach (int i in GetNumber())
            {
                Console.WriteLine(i);
            }
        }
    }
}
Output

1
2
3

IEnumerator ์‹ค์Šต

using System.Collections;

namespace yieldEx2
{
    class MyList
    {
        private int[] data = { 1, 2, 3, 4, 5 };
        //๋ฐฐ์—ด์€ ์ด๋ฏธ IEnumerator์™€ IEnumerable์„ ๊ตฌํ˜„ํ•˜๊ณ  ์žˆ๋‹ค.
        public IEnumerator GetEnumerator()
        {
            int i = 0;
            while (i < data.Length)
            {
                yield return data[i]; // 2. yield๋ฅผ  ๋งŒ๋‚˜๋ฉด ํ˜ธ์ถœ๋œ ๊ณณ์— ๋จผ์ € return์„ ํ•ด์ฃผ๊ณ  ๋‹ค์‹œ ํ˜ธ์ถœ๋  ๋•Œ๊นŒ์ง€ ๋Œ€๊ธฐ. 

                //IEnumator๋ฅผ ๋ฆฌํ„ด๊ฐ’์œผ๋กœ ๋’€์„๋•Œ์—๋Š” yield ๋ฌธ๋ฒ•์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ฆฌํ„ด์„ ํ•ด์•ผํ•œ๋‹ค.
                // yield๋ฅผ ๋งŒ๋‚˜๋ฉด ํ˜ธ์ถœ๋œ ๊ณณ์œผ๋กœ ๋‹ค์‹œ ๋Œ์•„๊ฐ€ ๊ฐ’์„ return ํ•œ ๋’ค ๋‹ค์‹œ ๋Œ์•„์™€ ๋น„๋™๊ธฐ์ ์œผ๋กœ ๋™์ž‘์„ ํ•œ๋‹ค.

                i++;// 4. ๋ณต๊ท€ํ›„ ํ•ด๋‹น์ฝ”๋“œ ์‹คํ–‰ํ•˜๊ณ  while๋ฌธ ๋™์ž‘ ์‹คํ–‰ํ•˜๋ฉฐ ์ผ๋ จ์˜ ๋ฐ˜๋ณต๊ณผ์ •์„ ์ง„ํ–‰.
            }
        }
        // IEnumerable ์ธํ„ฐํŽ˜์ด์Šค๋Š” GetEnumerator()๋ฉ”์†Œ๋“œ ํ•˜๋‚˜๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค. 
        // ์ด๋•Œ GetEnumerator()๋ฉ”์†Œ๋“œ๋Š” IEnumerator๋ฅผ ๊ตฌํ˜„ํ•œ ๊ฐ์ฒด๋ฅผ ๋ฆฌํ„ดํ•ด์ค€๋‹ค.

    }
    class Program
    {
        static void Main(string[] args)
        {
            var list = new MyList();

            foreach(var item in list) 
            // 1. var item in list์˜ in์—์„œ MyList ํด๋ž˜์Šค๋‚ด GetEnumerator๋กœ ์ง„์ž…
            // 3. ์„ ์–ธ๋œ ํ•˜๋‹จ ์ฝ”๋“œ ์‹คํ–‰ ํ›„ ๋‹ค์‹œ foreach ์ œ์–ด๋ถ€๋กœ ์˜ฌ๋ผ๊ฐ€ in์„ ๋งŒ๋‚˜๋ฉด ์ด์ „ yield return๋ฌธ ๋‹ค์Œ์œผ๋กœ ๋ณต๊ท€.
            {
                Console.WriteLine(item);
            }
        }
    }
}
Output

1
2
3
4
5

  • yield๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด IEnumerable, IEnumerator๋ฅผ ์ƒ์†๋ฐ›๋Š” ํด๋ž˜์Šค๋ฅผ ์ž‘์„ฑํ•ด ์ค„ ํ•„์š” ์—†๋‹ค.
  • IEnumerable ํด๋ž˜์Šค์—์„œ GetEnumerator() ๋ฉ”์„œ๋“œ๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ yield ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ์ฆ‰, GetEnumerator() ๋ฉ”์„œ๋“œ์—์„œ yield return๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ปฌ๋ ‰์…˜ ๋ฐ์ดํƒ€๋ฅผ ์ˆœ์ฐจ์ ์œผ๋กœ ํ•˜๋‚˜์”ฉ ๋„˜๊ฒจ์ฃผ๋Š” ์ฝ”๋“œ๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ , ๋ฆฌํ„ดํƒ€์ž…์œผ๋กœ IEnumerator ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋ฆฌํ„ดํ•  ์ˆ˜ ์žˆ๋‹ค.
  • C#์—์„œ Iterator ๋ฐฉ์‹์œผ๋กœ yield ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด, ๋ช…์‹œ์ ์œผ๋กœ ๋ณ„๋„์˜ Enumerator ํด๋ž˜์Šค๋ฅผ ์ž‘์„ฑํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค. ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์•Œ์•„์„œ ๋งŒ๋“ค์–ด์ฃผ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

๋น„๋™๊ธฐ์  ์‹คํ–‰์ด ๊ฐ€๋Šฅ

  • yield return๋ฌธ์„ ๋งŒ๋‚˜๋ฉด ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•œ ๊ณณ์— ๋ฆฌํ„ด์„ ํ•ด์ค€ ํ›„ ๋‹ค์‹œ ๋Œ์•„์™€์„œ ๋‹ค์Œ yield return๋ฌธ์„ ์‹คํ–‰ํ•œ๋‹ค. ์ฆ‰, ํ•˜๋‚˜์˜ ํ•จ์ˆ˜๋ฅผ ๋ชจ๋‘ ์‹คํ–‰ํ•  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฌ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ yield๋ฅผ ๋งŒ๋‚˜๋ฉด ์ž ์‹œ ํ•จ์ˆ˜ ์ค‘๊ฐ„์— ๋น ์ ธ๋‚˜์™€ ํ˜ธ์ถœํ•œ ๊ณณ์— ๋ฆฌํ„ด ๊ฐ’์„ ์ „๋‹ฌํ•ด์ฃผ๊ณ  ๋‹ค์‹œ ๋Œ์•„์™€ ๋งˆ์ € ํ•จ์ˆ˜๋ฅผ ์ง„ํ–‰ํ•˜๋Š” ์‹์œผ๋กœ ์™”๋‹ค ๊ฐ”๋‹ค ํ•˜๋ฉฐ ์‹คํ–‰๋˜๋Š” ๊ฒƒ์ด๋‹ค.

  • Enumerator : ๋ฐ์ดํ„ฐ ์š”์†Œ๋ฅผ ํ•˜๋‚˜์”ฉ ๋ฆฌํ„ดํ•˜๋Š” ๊ธฐ๋Šฅ์„ ํ•˜๋Š” ๊ฒƒ.

    • ์œ„์˜ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด์„œ C# ๋˜๋Š” .Net์—์„œ๋Š” IEnumerator๋ผ๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•ด์•ผ ํ•œ๋‹ค.
  • IEnumerator๋Š” Current(์†์„ฑ), MoveNext()(๋ฉ”์†Œ๋“œ), Reset()(๋ฉ”์†Œ๋“œ) 3๊ฐœ์˜ ๋ฉค๋ฒ„๋กœ ์ด๋ฃจ์–ด์ ธ์žˆ๋‹ค.

    • ๋”ฐ๋ผ์„œ, Enumerator๊ฐ€ ๋˜๊ธฐ์œ„ํ•ด์„œ๋Š” Current(์†์„ฑ), MoveNext()(๋ฉ”์†Œ๋“œ)๋ฅผ ๋ฐ˜๋“œ์‹œ ๊ตฌํ˜„ํ•ด์ค˜์•ผ ํ•œ๋‹ค.
  • ์ปฌ๋ ‰์…˜ ํด๋ž˜์Šค๋Š” Enumeration์ด ๊ฐ€๋Šฅํ•œ ํด๋ž˜์Šค์ธ๋ฐ, ์ด๋Ÿฌํ•œ ํด๋ž˜์Šค๋“ค์„ Enumerableํด๋ž˜์Šค๋ผ๊ณ  ํ•œ๋‹ค.

    • ์ด Enumerable ํด๋ž˜์Šค๋Š” IEnumerable ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•ด์•ผํ•œ๋‹ค.
  • IEnumerable ์ธํ„ฐํŽ˜์ด์Šค๋Š” GetEnumerator()๋ฉ”์†Œ๋“œ ํ•˜๋‚˜๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค.

    • ์ด๋•Œ GetEnumerator()๋ฉ”์†Œ๋“œ๋Š” IEnumerator๋ฅผ ๊ตฌํ˜„ํ•œ ๊ฐ์ฒด๋ฅผ ๋ฆฌํ„ดํ•ด์ค€๋‹ค.
  • ์ปฌ๋ ‰์…˜ ํƒ€์ž…์ด๋‚˜ ๋˜๋Š” Enumerable ํด๋ž˜์Šค์—์„œ GetEnumerator()๋ฉ”์†Œ๋“œ๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ yield ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

  • GetEnumerator() ๋ฉ”์†Œ๋“œ์—์„œ yield return์„ ์‚ฌ์šฉํ•˜๋ฉด ์ปฌ๋ ‰์…˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆœ์ฐจ์ ์œผ๋กœ ํ•˜๋‚˜์”ฉ ๋„˜๊ฒจ์ฃผ๋Š” ์ฝ”๋“œ๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๊ณ , ๋ฆฌํ„ดํƒ€์ž…์€ IEnumerator ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋ฆฌํ„ดํ•  ์ˆ˜ ์žˆ๋‹ค.


yield๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ข‹์€ ๊ฒฝ์šฐ.

  • ๋งŒ์•ฝ ๋ฐ์ดํƒ€์˜ ์–‘์ด ์ปค์„œ ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋ฅผ ํ•œ๋ฒˆ์— ๋ฆฌํ„ดํ•˜๊ธฐ ๋ณด๋‹ค ์กฐ๊ธˆ์”ฉ ๋ฆฌํ„ดํ•˜๋Š” ๊ฒƒ์ด ๋” ํšจ์œจ์ ์ผ ๊ฒฝ์šฐ.
    • ์˜ˆ๋ฅผ ๋“ค์–ด, ์–ด๋–ค ๊ฒ€์ƒ‰์—์„œ 1๋งŒ ๊ฐœ์˜ ์ž๋ฃŒ๊ฐ€ ์กด์žฌํ•˜๋Š”๋ฐ, UI์—์„œ 10๊ฐœ์”ฉ๋งŒ On Demand๋กœ ํ‘œ์‹œํ•ด ์ฃผ๋Š”๊ฒŒ ์ข‹์„ ์ˆ˜๋„ ์žˆ๋‹ค. ์ฆ‰, ์‚ฌ์šฉ์ž๊ฐ€ 20๊ฐœ๋ฅผ ์›ํ•  ์ง€, 1000๊ฐœ๋ฅผ ์›ํ•  ์ง€ ๋ชจ๋ฅด๊ธฐ ๋•Œ๋ฌธ์—, ์ผ์ข…์˜ ์ง€์—ฐ ์‹คํ–‰(Lazy Operation)์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ์ด ๋‚˜์„ ์ˆ˜ ์žˆ๋‹ค.

  • ์–ด๋–ค ๋ฉ”์„œ๋“œ๊ฐ€ ๋ฌด์ œํ•œ์˜ ๋ฐ์ดํƒ€๋ฅผ ๋ฆฌํ„ดํ•  ๊ฒฝ์šฐ.
    • ์˜ˆ๋ฅผ ๋“ค์–ด, ๋žœ๋ค ์ˆซ์ž๋ฅผ ๋ฌด์ œํ•œ ๊ณ„์† ๋ฆฌํ„ดํ•˜๋Š” ํ•จ์ˆ˜๋Š” ๊ฒฐ๊ตญ ์ „์ฒด ๋ฆฌ์ŠคํŠธ๋ฅผ ๋ฆฌํ„ดํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์— yield ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๊ตฌํ˜„ํ•˜๊ฒŒ ๋œ๋‹ค.

  • ๋ชจ๋“  ๋ฐ์ดํƒ€๋ฅผ ๋ฏธ๋ฆฌ ๊ณ„์‚ฐํ•˜๋ฉด ์†๋„๊ฐ€ ๋А๋ ค์„œ ๊ทธ๋•Œ ๊ทธ๋•Œ On Demand๋กœ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒƒ์ด ์ข‹์€ ๊ฒฝ์šฐ.
    • ์˜ˆ๋ฅผ ๋“ค์–ด ์†Œ์ˆ˜(Prime Number)๋ฅผ ๊ณ„์† ๋ฆฌํ„ดํ•˜๋Š” ํ•จ์ˆ˜์˜ ๊ฒฝ์šฐ, ์†Œ์ˆ˜ ์ „์ฒด๋ฅผ ๊ตฌํ•˜๋ฉด (๋ฌผ๋ก  ๋ฌด์ œํ•œ์˜ ๋ฐ์ดํƒ€๋ฅผ ๋ฆฌํ„ดํ•˜๋Š” ๊ฒฝ์šฐ์ด๊ธฐ๋„ ํ•˜์ง€๋งŒ) ์‹œ๊ฐ„์ƒ ๋งŽ์€ ๊ณ„์‚ฐ ์‹œ๊ฐ„์ด ์†Œ์š”๋˜๋ฏ€๋กœ ๋‹ค์Œ ์†Œ์ˆ˜๋งŒ ๋ฆฌํ„ดํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค์–ด ์†Œ์š” ์‹œ๊ฐ„์„ ๋ถ„์‚ฐํ•˜๋Š” ์ง€์—ฐ ๊ณ„์‚ฐ(Lazy Calculation)์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

yield์™€ ์˜ˆ์™ธ

yield return๋ฌธ์€ try-catch ๋ฌธ ์•ˆ์—์„œ ์“ธ ์ˆ˜ ์—†๋‹ค.
yield break๋ฌธ์€ try-catch ๋ฌธ ์•ˆ์—์„  ์“ธ ์ˆ˜ ์žˆ์ง€๋งŒ finally ์—์„  ์“ธ ์ˆ˜ ์—†๋‹ค.


์ตœ์ข… ์ •๋ฆฌ

  • foreach๋ฌธ์„ ํ†ตํ•ด ์ˆœํšŒํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ํ•ด๋‹น ์ž๋ฃŒ๊ตฌ์กฐ ํƒ€์ž…(์—ฌ๊ธฐ์„  ํด๋ž˜์Šค?)์ด GetEnumerator() ๋ฉ”์†Œ๋“œ๋ฅผ ํฌํ•จํ•ด์•ผํ•œ๋‹ค.
    • ์ด๋•Œ GetEnumerator์˜ ๋ฐ˜ํ™˜ ํƒ€์ž…์€ IEnumerator()์ธ๋ฐ ์ด๋Š” Current ์™€ MoveNext()๋ฅผ ํฌํ•จํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.
    • ์ฆ‰, ์‚ฌ์šฉ์ž๊ฐ€ ๋ณ„๋„๋กœ Current์™€ MoveNext()๋ฅผ ์„ ์–ธํ•œ ํด๋ž˜์Šค๊ฐ€ ์žˆ๋‹ค๋ฉด ํ•ด๋‹น ํด๋ž˜์Šคํƒ€์ž…์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ˜ํ™˜ํ•ด๋„ ๋œ๋‹ค.

Ex : 

public class Computer
{
    List<Device> _parts;

    public Computer()
    {
        _parts = new List<Device>()
        {
            new Device() { Name = "CPU"},
            new Device() { Name = "MotherBoard"},
        };
    }

    public Device[] GetDevices()
    {
        return _parts.ToArray();
    }

    public IEnumerator<Device> GetEnumerator()
    {
        foreach (var device in GetDevices())
        {
            yield return device;
        }
    }
}

//////////////////IEnumerator ํƒ€์ž… ๋ฐ˜ํ™˜์˜ˆ์‹œ

public class Computer
{
    List<Device> _parts;

    public Computer()
    {
        _parts = new List<Device>()
        {
            new Device() { Name = "CPU"},
            new Device() { Name = "MotherBoard"},
        };
    }

    public Device[] GetDevices()
    {
        return _parts.ToArray();
    }

    public PartList GetEnumerator()
    {
        return new PartList(this);
    }

    public class PartList
    {
        Device [] _devices;
        public PartList(Computer computer) { _devices = computer.GetDevices(); }

        int _current = -1;

        public Device Current
        {
            get { return _devices[_current]; }
        }

        public bool MoveNext() 
        { 
            if (_current >= _devices.Length - 1)
            {
                return false;
            }

            _current++;
            return true;
        }
    }
}

////////////////////////์‚ฌ์šฉ์ž ์ •์˜ ํด๋ž˜์Šค ํƒ€์ž… ๋ฐ˜ํ™˜์˜ˆ์‹œ
  • ์ถ”๊ฐ€์ ์œผ๋กœ ๊ธฐ์กด ์ •์˜๋œ IEnumerator ํด๋ž˜์Šค์™€ IEnumerable ํด๋ž˜์Šค๋ฅผ ์ƒ์†๋ฐ›์•„๋„ ๋œ๋‹ค!

[Reference] : https://www.sysnet.pe.kr/2/0/12403

=> IEnumerable, IEnumerator ๋‚ด์šฉ ์ฐธ๊ณ 

[Reference] : https://ansohxxn.github.io/c%20sharp/enumerate/

=> yield & IEnumerable, IEnumerator ๋‚ด์šฉ ์ฐธ๊ณ