yield
호출자(Caller)에게 컬렉션 데이터를 하나씩 리턴할 때 사용한다. Enumerator(Iterator)라고 불리는 이러한 기능은 집합적인 데이터 셋으로부터 데이터를 하나씩 호출자에게 보내주는 역할을 한다.
- yield return : 컬렉션 데이터를 하나씩 리턴하는데 사용
- yield break : 리턴을 중지하고 iteration 루프를 빠져나올 때 사용
예제 1)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
using System;
using System.Collections.Generic;
class Program
{
static IEnumerable<int> GetNumber()
{
yield return 1; // 첫번째 루프에서 리턴되는 값
yield return 2; // 두번째 루프에서 리턴되는 값
yield return 3; // 세번째 루프에서 리턴되는 값
}
static void Main(string[] args)
{
foreach (int num in GetNumber())
{
Console.WriteLine(num);
}
}
}
|
cs |
출력)
1
2
3
-> 한꺼번에 호출하는게 아닌 한번 호출시마다 다음 yield return을 반환한다.
이러한 방식은 다음과 같은 경우 유용하게 사용한다.
1) 데이터 양이 커서 모든 데이터를 한꺼번에 리턴하는 것보다 조금씩 리턴하는 것이 효과적일 경우
2) 무제한의 데이터를 리턴할 경우, 예를 들어 랜덤 숫자를 무제한 리턴할 경우 전체 리스트를 리턴할 수 없기 때문에 yield를 사용해 구현한다.
3) 모든 데이터를 미리 계산하여 속도가 느린 경우. 한꺼번에 많은 양을 처리할 경우 속도가 느리므로 필요한 값만 리턴하여 사용한다(예 :소수 전체를 구하는 함수. 한꺼번에 모든 데이터를 리턴하는 것보다 계산된 값만 리턴)
yield와 Enumerator
C#에서 yield가 사용되는 곳은 집합적 데이터를 갖고 있는 컬렉션 클래스이다. 일반적으로 컬렉션 클래스는 데이터 요소를 하나씩 사용하기 위해 enumerator(Iterator)를 구현하는데 이떄 yield를 사용하면 된다.
-> yield를 이용하여 컬렉션 데이터를 순차적으로 하나씩 넘겨주는 코드를 구현, 리턴타입으로 IEnumerator 인터페이스를 리턴한다. C#에서 yield를 사용하면 Enumerator 클래스 작성 필요없이 사용가능하다.
예제 2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
using System;
using System.Collections;
public class MyList
{
private int[] data = { 1, 2, 3, 4, 5 };
public IEnumerator GetEnumerator()
{
int i = 0;
while (i < data.Length)
{
yield return data[i];
i++;
}
}
//...
}
class Program
{
static void Main(string[] args)
{
// foreach 사용하여 Iteration
var list = new MyList();
foreach (var item in list)
{
Console.WriteLine(item);
}
// MoveNext를 사용한 수동 Iteration
IEnumerator it = list.GetEnumerator();
it.MoveNext();
Console.WriteLine(it.Current); // 1
it.MoveNext();
Console.WriteLine(it.Current); // 2
}
}
|
cs |
MS 예제 -1) IEnumerable return method
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
public class PowersOf2
{
static void Main()
{
// Display powers of 2 up to the exponent of 8:
foreach (int i in Power(2, 8))
{
Console.Write("{0} ", i);
}
}
public static System.Collections.Generic.IEnumerable<int> Power(int number, int exponent)
{
int result = 1;
for (int i = 0; i < exponent; i++)
{
result = result * number;
yield return result;
}
}
// Output: 2 4 8 16 32 64 128 256
}
|
cs |
MS 예제 -2) get accessor
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
public class PowersOf2
{
static void Main()
{
// Display powers of 2 up to the exponent of 8:
foreach (int i in Power(2, 8))
{
Console.Write("{0} ", i);
}
}
public static System.Collections.Generic.IEnumerable<int> Power(int number, int exponent)
{
int result = 1;
for (int i = 0; i < exponent; i++)
{
result = result * number;
yield return result;
}
}
// Output: 2 4 8 16 32 64 128 256
}
|
cs |
참고링크
www.csharpstudy.com/CSharp/CSharp-yield.aspx
docs.microsoft.com/ko-kr/dotnet/csharp/language-reference/keywords/yield
'Software Development > C#' 카테고리의 다른 글
[Effective C#] const보다는 readonly 사용하기 (0) | 2021.01.13 |
---|---|
[Effective C#] 지역변수 선언은 var를 사용/var 이해하기 (0) | 2021.01.09 |
[Effective C#] C# 표준 Dispose 패턴 이해하기 (0) | 2021.01.02 |
[Effective C#] C# 정적 클래스 멤버 초기화 유의사항 (0) | 2020.12.31 |
[Effective C#]C# 멤버 초기화 - 할당 구문보다 멤버 초기화를 사용한다. (0) | 2020.12.30 |