해당 코드는 [시작하세요! C# 6.0] 도서 및 [MSDN]을 참조하였다.
제목이 난해하게 기재되어 있으나,
foreach 가 어떻게 동작하는지 보여주는 코드와 같다.
using System;
using System.Collections;
namespace ConsoleApp1
{
class Hardware { }
class USB
{
string name;
public USB(string name) { this.name = name; }
public override string ToString()
{
return name;
}
}
class Notebook : Hardware, IEnumerable
{
private USB[] usbList = new USB[] { new USB("USB1"), new USB("USB2") };
public IEnumerator GetEnumerator()
{
return new USBEnumerator(usbList);
}
public class USBEnumerator : IEnumerator
{
int pos = -1;
int length = 0;
object[] list;
public USBEnumerator(USB[] usb)
{
list = usb;
length = usb.Length;
}
public object Current
{
get { return list[pos]; }
}
public bool MoveNext()
{
if (pos >= length - 1)
{
return false;
}
pos++;
return true;
}
public void Reset()
{
pos = -1;
}
}
}
class Program
{
static void Main(string[] args)
{
Notebook notebook = new Notebook();
foreach (USB usb in notebook)
{
Console.WriteLine(usb);
}
}
}
}
C# 의 foreach 구문은 IEnumerable 인터페이스를 상속하여 동작한다.
즉 IEnumerable 인터페이스를 상속받아 구현하여 동작시키면 foreach 의 동작원리를
이해할 수 있게 된다.
C#내의 'in' 구문은 IEnumerator 인터페이스 중
MoveNext 부분과 적중한다.
foreach 구문의 해석은
foreach → notebook → in → USB usb
순서로 진행되는데,
foreach 부분은 GetEnumerator 함수와 매칭되어 UsbEnumerator(usbList) 를 반환한다.
다음으로
in 부분은 MoveNext 함수와 매칭되어, MoveNext 함수가 호출된다.
즉 pos 조건을 충족하기 전까지 계속해서 foreach 문을 도는 것이다. (false 를 반환하기 전까지)
여기서 foreach 는 한 문장이 끝날 때 마다
public object Current 를 실행하여 해당하는 열거 번째를 반환해야 한다.
pos 를 이용하여 해당하는 번지수의 object 가 반환될 수 있게 처리 하였다.
끝.
여기서 만약 MoveNext 함수를 수정하여 length 를 초과하게 바꾼다면
C++ 의 Vector 오류와 비슷하게 OutOfRange 에러를 출력한다.
맺음말.
이 포스팅은 IEnumable 을 직접 이런식으로 '사용해라!' 는 목적으로 작성한 것은 아니다.
단순히 foreach 가 어떤식으로 구성되어 있는지 파악하는데 도움이 되라 작성 하였다.
'Programming > C#' 카테고리의 다른 글
[C#] async & await 을 lamdba 에서 사용시 오류 (0) | 2021.03.19 |
---|---|
[C#] 델리게이트와 이벤트의 차이점 (0) | 2021.03.04 |
[C#] 형변환 [as, is] (0) | 2021.02.27 |
[C#] 인터페이스 사용 이유. (0) | 2020.12.14 |
[C#] Thread, Task 의 간단한 사용법 (0) | 2020.12.01 |