개발공부/C#

[Effective C#] 아이템 37 : 쿼리를 사용할 때는 즉시 평가보다 지연 평가가 낫다.

개발자 찐빵이 2021. 12. 12. 22:17
728x90

지연 평가와 즉시 평가

쿼리를 정의하면 결과 데이터나 시퀀스를 즉각적으로 얻어오지 않는다.
그저 어떤 과정으로 작업을 수행할지 절차를 정의하는 것이다.

지연 평가: 쿼리의 결과를 이용해서 순회를 순행해야 결과가 생성되는 것
즉시 평가: 일반 변수를 사용하는 것처럼 즉각적으로 값을 얻어오는 것

지연 평가와 즉시 평가의 차이

예시 1
시퀀스 생성 후 두 차례에 걸쳐 순회하는 코드

private static IEnumerable<TResult> Generate<TResult>(
    int number, Func<TResult> generator)
{
    for (var i = 0; i < number; i++)
        yield return generator();
}

private static void LazyEvaluation()
{
    WriteLine($"Start time for Test One: {DateTime.Now:T}");
    var sequence = Generate(10, () => DateTime.Now);

    WriteLine("Waiting....\tPress Return");
    ReadLine();

    WriteLine("Iterating...");
    foreach (var value in sequence)
        WriteLine($"{value:T}");

    WriteLine("Waiting....\tPress Return");
    ReadLine();

    WriteLine("Iterating...");
    foreach (var value in sequence)
        WriteLine($"{value:T}");
}

결과

Start time for Test One: 6:43:23 PM
Waiting....        Press Return

Iterating...
6:43:31 PM
...
6:43:31 PM
Waiting....        Press Return

Iterating...
6:43:42 PM
...
6:43:42 PM

지연 평가 특징

시퀀스를 매번 순회할 때마다 서로 다른 시간 정보가 출력된다.
시퀀스는 시퀀스 내 개별 요소들을 생성하는 방법을 나타내는 코드를 가지고 있다.

예시 2
쿼리의 결과를 대상으로 추가 쿼리를 수행하는 코드

var sequence1 = Generate(10, () => DateTime.Now);
var sequence2 = from value in sequence1
                select value.ToUniversalTime();

sequence2는 sequence1이 생성한 값을 변경하는 것이 아니라 완전히 새로운 값을 만들어낸다.
쿼리 표현식은 지연 평가를 수행하기 때문에 이론적으로 무한 시퀀스를 표현하는 것이 가능하다.

전체 시퀀스가 필요한 메서드를 사용할 때 염두에 두어야 하는 사항

  1. 시퀀스가 무한정 지속될 가능성이 있다면 메서드를 사용할 수 없다.
  2. 시퀀스가 무한이 아니더라도 시퀀스를 필터링하는 쿼리 메서드는 다른 쿼리보다 먼저 수행하는 것이 좋다.
    선행 단계에서 컬렉션의 요소를 필터링하여 개수를 줄일 수 있으면, 다음으로 수행할 쿼리의 성능을 개선할 수 있기 때문이다.
반응형