커스텀 열거자(Custom Enumerator) 구현을 통한 For-In 루프 최적화

델파이의 for..in 루프는 기본적으로 배열이나 TList 같은
표준 컬렉션에서 작동합니다. 하지만 직접 만든
복잡한 자료구조나 특정 조건에 맞는 데이터만 순회하고 싶을 때
GetEnumerator 함수를 클래스에 구현하면,
표준 컬렉션이 아니더라도 for..in 문법을 사용할 수 있습니다.
이를 통해 내부 구현을 감추면서도 사용자에게는
매우 직관적인 순회 인터페이스를 제공할 수 있습니다.
program CustomEnumeratorExample;
{$APPTYPE CONSOLE}
uses
System.SysUtils;
type
// 홀수만 순회하는 커스텀 열거자 클래스
TOddEnumerator = class
private
FIndex: Integer;
FData: TArray<Integer>;
public
constructor Create(AData: TArray<Integer>);
function MoveNext: Boolean; // 다음 항목 존재 여부 확인
property Current: Integer read FData[FIndex]; // 현재 값 반환
end;
// 열거자를 소유한 컨테이너 클래스
TOddContainer = class
private
FItems: TArray<Integer>;
public
constructor Create(AItems: TArray<Integer>);
// for..in 루프가 호출하는 필수 함수
function GetEnumerator: TOddEnumerator;
end;
{ TOddEnumerator }
constructor TOddEnumerator.Create(AData: TArray<Integer>);
begin
FData := AData;
FIndex := -1; // 첫 MoveNext 호출 시 0이 되도록 설정
end;
function TOddEnumerator.MoveNext: Boolean;
begin
Result := False;
while FIndex < High(FData) do
begin
Inc(FIndex);
if (FData[FIndex] mod 2 <> 0) then // 홀수 조건 체크
begin
Result := True;
Break;
end;
end;
end;
{ TOddContainer }
constructor TOddContainer.Create(AItems: TArray<Integer>);
begin
FItems := AItems;
end;
function TOddContainer.GetEnumerator: TOddEnumerator;
begin
Result := TOddEnumerator.Create(FItems);
end;
var
Container: TOddContainer;
Num: Integer;
begin
// 1부터 10까지의 배열을 가진 컨테이너 생성
Container := TOddContainer.Create([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
try
Writeln('--- 컨테이너 내의 홀수만 출력 ---');
// 커스텀 열거자 덕분에 for..in 루프 사용 가능
for Num in Container do
begin
Write(Num, ' ');
end;
Writeln;
finally
Container.Free;
end;
Readln;
end.
실행 결과
--- 컨테이너 내의 홀수만 출력 ---
1 3 5 7 9
GetEnumerator: 클래스 내에 이 이름의 함수가 있고,
그 반환 객체가 MoveNext와 Current 멤버를 가지고 있다면
델파이 컴파일러는 이를 열거 가능한 객체로 인식합니다.
MoveNext: 다음 데이터로 이동하고 성공 여부를 반환합니다.
이 안에서 필터링 로직(예: 홀수 판별)을 구현할 수 있습니다.
Current: 현재 인덱스의 실제 값을 반환하는 읽기 전용 속성입니다.
장점: 복잡한 필터링 로직을 비즈니스 코드에서 분리하여
캡슐화할 수 있으며, 코드의 가독성이 획기적으로 향상됩니다.
커스텀 열거자를 클래스로 만들면 힙 메모리 할당이 발생합니다.
성능이 매우 중요한 루프라면 클래스 대신
**레코드(Record)**를 사용하여 열거자를 구현하면 메모리 할당
오버헤드 없이 동일한 기능을 수행할 수 있습니다.
최신 VCL 라이브러리들도 성능 최적화를 위해
레코드 기반 열거자를 많이 사용합니다.

#델파이 #delphi #GetEnumerator #MoveNext #Current
#ForInLoop #IteratorPattern #ObjectPascal #커스텀컬렉션 #코드캡슐화
'Delphi > 클래스' 카테고리의 다른 글
| 클래스 참조(Class Reference)와 가상 생성자를 이용한 동적 객체 생성 (0) | 2026.03.25 |
|---|---|
| TStringList 정렬, 중복 제거, 파일 입출력 (0) | 2025.11.11 |
| TList와 TList<T>의 차이 및 실무 활용 (0) | 2025.11.10 |
| 클래스(Class) 기반 객체 설계 기초 (0) | 2025.10.17 |
| 메모리 스트림(TMemoryStream) 활용하기 (0) | 2025.10.01 |
댓글