[포스트-4][LINQ] 수율-성능

[Post-4][LINQ] 수율-성능





수익률 반환을 사용하면 데이터를 쿼리할 때 성능이 크게 향상됩니다. 반복될 때만 데이터가 반환되기 때문입니다.

예를 들어 컬렉션에서 여러 쿼리를 실행해야 하는 경우 한 가지 방법은 각 쿼리에 대해 컬렉션을 반복하는 것입니다. 다른 방법은 모든 쿼리를 함께 컴파일한 다음 컬렉션에서 쿼리를 한 번 실행하는 것입니다. 두 번째 방법은 성능이 더 좋고 메모리 사용량도 적습니다.

위의 사항을 설정하기 위한 예를 살펴보겠습니다. [소스 코드는 github gist로 블로그 끝에 제공됩니다]. 이 예에서는 숫자 목록을 필터링하고 6의 배수를 얻습니다.

아래는 1부터 20까지의 숫자 목록입니다.

List<int> numbers = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };

두 단계 프로세스로 필터링을 수행할 수 있습니다.
  • 먼저 2로 나누어지는 숫자를 필터링합니다.
  • 그런 다음 3으로 나누어지는 숫자를 필터링합니다.

  • 다음은 숫자를 각각 2 또는 3으로 나눌 수 있는 경우 true를 반환하는 bool DivideBy2(int x) 및 bool DivideBy3(int x)의 두 함수입니다.

    private bool DivideBy2(int x)       
    {           
     if (x % 2 == 0)
     {                
       return true;         
     }           
     else 
     {               
       return false;           
     }       
    }
    
    private bool DivideBy3(int x)       
    {           
     if (x % 3== 0)
     {                
       return true;         
     }           
     else 
     {               
       return false;           
     }       
    }
    

    이제 주어진 술어를 기반으로 주어진 열거 가능 항목을 필터링하는 IEnumerable에 필터 확장을 만들 수 있습니다.

    public static IEnumerable<int> **FilterWithOutYield**(
    this IEnumerable<int> **enumerable**, Func<int, bool> **func**)        
    {
      IEnumerator<int> **enumerator **= enumerable.GetEnumerator();
      List<int> result = new List<int>();
      **while (enumerator.MoveNext())**
       {
          **if (func(enumerator.Current))**
          {
            **result.Add(enumerator.Current);**
          }
       }
      **return result as IEnumerable<int>;**
    }
    

    위 함수 **FilterWithOutYield **에는 두 개의 매개변수가 있습니다.
  • enumerable: 이 **FilterWithOutYield **가 실행되는 데이터입니다.
  • func: 이 함수는 필터 역할을 하며 항목 필터링 여부를 결정하는 데 도움이 됩니다.

  • 함수는 여기서 3가지 일을 합니다.
  • 열거자를 사용하여 while 루프에서 열거 가능한 **을 반복합니다. [while 루프**]
  • 주어진 조건자 기능을 만족하는 숫자를 필터링합니다. **[**인 경우]
  • 목록에 추가하고 반환합니다*. [결과]*

  • 처음에 생성한 20개의 숫자 목록에서 위의 **FilterWithOutYield **를 호출해 보겠습니다.

    List<int> **numbers **= new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };
                List<int> multiplesOfSix =
                    (
    numbers.FilterWithOutYield(**DivideBy2**) // returns a list 
           .FilterWithOutYield(**DivideBy3**) // returns a list
    
    ) as List<int>;
    

    위의 코드에서 FilterWithOutYield *는 숫자에서 *두 번 호출됩니다.
  • 처음에는 **DivideBy2 **가 조건자로 사용됩니다. 이 함수는 2로 나눌 수 있는 모든 숫자를 필터링하고 목록을 반환합니다.
  • 두 번째로 **DivideBy3 **이 조건자로 사용됩니다. 이 함수는 위의 숫자 목록에서 3으로 나누어지는 모든 숫자를 필터링하고 다른 목록을 반환합니다.

  • 마지막으로 6으로 나눌 수 있는 숫자 목록이 반환됩니다. 여기에서 컬렉션을 두 번 반복하고 각 단계에서 새 목록을 반환하는 것을 관찰하면 됩니다.

    I.e. If FilterWithOutYield is chained n times , the iterations are also proportionately increased and also the number of lists returned.



    이제 Yield를 사용하여 동일한 작업을 수행하는 더 나은 방법을 살펴보겠습니다. 아래는 열거형을 필터링하고 **yield return.*을 사용하는 FilterWithYield *함수입니다.

    public static IEnumerable<int> FilterWithYield(
    this IEnumerable<int> enumerable, Func<int,bool> func)
    {
       IEnumerator<int> enumerator = enumerable.GetEnumerator();
       while (enumerator.MoveNext()) 
       {
         if (**func(enumerator.Current)**)
         {
           **yield return enumerator.Current;**
         }
       }
     }
    

    참고로 위의 방법에서는 목록을 반환하지 않고 대신 수율 반환을 수행합니다.

    열거형에서 이 메서드를 호출하고 어떻게 작동하는지 살펴보겠습니다.

    List<int> numbers = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };
    
    IEnumerable<int> multiplesOfSixUsingYield =
    numbers.FilterWithYield(**DivideBy2**) // The list is not iterated.
           .FilterWithYield(**DivideBy3**); //Instead enumerator is returned
    

    위의 코드는 **숫자 **를 반복하지 않으므로 **DivideBy2 ** 또는 **DivideBy3 **메서드 중 하나로 이동하지 않습니다. 대신 **DivideBy2 ** 및 **DivideBy3 ** 메서드를 모두 사용하여 열거 가능 항목을 필터링하는 열거자가 생성됩니다.

    위 코드에서 컬렉션을 가져오려면 multiplesOfSixUsingYield *는 아래와 같이 **foreach*를 사용하거나 **ToList() *또는 *ToArray()**와 같은 확장 메서드를 사용하여 반복해야 합니다.

    foreach (int x in multiplesOfSixUsingYield) 
    {              
       Console.WriteLine(x);
    }
    

    수율 반환으로 인해 열거 가능 항목은 FilterWithYield 메서드가 사용되는 횟수에 관계없이 한 번만 반복되므로 시간이 향상되고 메모리 공간도 줄어듭니다.







    희망, 당신은 기사를 좋아했습니다. 계속 읽으세요. 감사합니다.

    좋은 웹페이지 즐겨찾기