C\#에서 yield 키워드 에 대한 심도 있 는 분석

11879 단어 c#yield키워드
머리말
얼마 전에 yield 키 워드 를 알 게 되 어 괜 찮 았 습 니 다.오늘 은 yield 키워드 의 용법 을 공유 해 드 리 겠 습 니 다.yield return 반환 집합 은 모든 집합 요 소 를 한꺼번에 되 돌려 주 는 것 이 아니 라 한 번 에 하나의 요 소 를 되 돌려 주 는 것 입 니 다.구체 적 으로 어떻게 yield return 을 사용 하여 집합 으로 돌아 갑 니까?우리 같이 아래 를 봅 시다.
yield 사용 안내
yield return 과 yield break:
우 리 는 일반적인 순환 이 집합 으로 돌아 가 는 사용 동작 을 보 았 다.(1-100 의 짝수 로 돌아 가기)

 class Program
 {
 static private List<int> _numArray; //    1-100  100   

 Program() //    。                     1-100 100     
 {
  _numArray = new List<int>(); //               ,            _numArray  

  for (int i = 1; i <= 100; i++)
  {
  _numArray.Add(i); // 1 100           
  }
 }

 static void Main(string[] args)
 {
  new Program();

  TestMethod();


 }

 //   1 100       
 static public void TestMethod()
 {
  foreach (var item in GetAllEvenNumberOld())
  {
  Console.WriteLine(item); //      
  }
 }

 /// <summary>
 ///           
 /// </summary>
 /// <returns></returns>
 static IEnumerable<int> GetAllEvenNumberOld()
 {
  var listNum = new List<int>();
  foreach (int num in _numArray)
  {
  if (num % 2 == 0) //       
  {
   listNum.Add(num); //      

  }
  }
  return listNum;
 } 
 }
그리고 우 리 는 yield return 을 사용 하여 집합 작업 으로 돌아 가 는 것 을 다시 봅 시다.

 class Program
 {
 static private List<int> _numArray; //    1-100  100   

 Program() //    。                     1-100 100     
 {
  _numArray = new List<int>(); //               ,            _numArray  

  for (int i = 1; i <= 100; i++)
  {
  _numArray.Add(i); // 1 100           
  }
 }

 static void Main(string[] args)
 {
  new Program();

  TestMethod();


 }

 //   1 100       
 static public void TestMethod()
 {
  foreach (var item in GetAllEvenNumber())
  {
  Console.WriteLine(item); //      
  }
 } 

 //  Yield Return      
 static IEnumerable<int> GetAllEvenNumber()
 {

  foreach (int num in _numArray)
  {
  if (num % 2 == 0) //       
  {
   yield return num; //      

  }
  }
  yield break; //          ,         ,        
  //              ,            。
 }


 }
평소 return 과 비교
위 에서 우 리 는 yield return 의 사용 방법 을 보 았 습 니 다.그러면 이것 은 return 복귀 집합 과 어떤 차이 가 있 습 니까?우 리 는 다음 사례 를 보고 분석 했다.
우 리 는 먼저 returun 을 통 해 집합 으로 돌아 가 는 사례 를 살 펴 보 자.

 class Program
 { 
 static void Main(string[] args)
 {
  foreach (var item in GetNums())
  {
  Console.WriteLine($" common return:{item}");
  }
 } 

 /// <summary>
 ///   return     
 /// </summary>
 /// <returns></returns>
 public static IEnumerable<int> GetNums()
 {
  var listNum = new List<int>();
  for (int i = 0; i < 10; i++)
  {
  Console.WriteLine($"yield return:{i}");
  listNum.Add(i);
  }
  return listNum;
 }
 }

코드 의 실행 결 과 를 통 해 여기 서 돌아 온 결 과 를 볼 수 있 습 니 다.yield return 과 comment return 은 양쪽 으로 나 뉘 어 있 습 니 다.하 나 를 실행 하고 다른 하 나 를 실행 하 세 요.불 간섭.
우 리 는 이어서 yield return 을 사용 하여 집합 으로 돌아 가 는 것 을 보 았 다.

 class Program
 { 
 static void Main(string[] args)
 {
  foreach (var item in GetNumsYield())
  {
  Console.WriteLine($" common return:{item}");
  }
 }

 /// <summary>
 ///   yield return     
 /// </summary>
 /// <returns></returns>
 public static IEnumerable<int> GetNumsYield()
 {
  for (int i = 0; i < 10; i++)
  {
  Console.WriteLine($"yield return:{i}");
  yield return i;
  }
 } 
 }

우 리 는 이 운행 결 과 를 보 았 습 니 다.여기 서 yield return 과 comment return 의 출력 이 완전히 바 뀌 었 습 니 다.이것 은 한 번 호출 하면 하나의 요 소 를 되 돌려 준 다 는 것 을 설명 한다.
위의 사례 를 통 해 알 수 있 듯 이 yield return 은 모든 실행 이 끝 난 후에 야 한꺼번에 돌아 오 는 것 이 아니다.한 번 만 호출 하고 결 과 를 되 돌려 주 는 요소 입 니 다.이것 이 바로 수요 에 따라 공급 하 는 것 이다.
해석 정의 클래스
우 리 는 이미 yield 의 용법 과 그것 과 평상시 의 귀환 의 차 이 를 대충 이해 했다.우 리 는 그 운행 원 리 를 계속 볼 수 있다.우 리 는 먼저 이런 사례 를 본다(0-10 에서 무 작위 로 다섯 개의 숫자 를 되 돌려 준다).
우 리 는SharpLab을 통 해 코드 를 역 컴 파일 했 습 니 다.우 리 는 yield 가 구체 적 으로 상세 하 게 실현 되 었 음 을 알 수 있 습 니 다.

 
우 리 는 yield 내부 에 교체 기 가 포함 되 어 있 는 것 을 보 았 다.이렇게 실현 되 는 것 이 반복 된다.동시에 포함state 필드,지난번 기록 을 저장 하 는 데 사 용 됩 니 다.current 는 현재 값 을 포함 하고initialThreadId 에서 현재 스 레 드 id 를 가 져 옵 니 다.그 중에서 도 주요 한 방법 은 교체 기 방법 인 MoveNext()다.우 리 는 역 컴 파일 결과 에 따라 yiled 와 비슷 한 종 류 를 실현 합 니 다.

 /// <summary>
 ///   yield      
 /// </summary>
 public sealed class GetRandomNumbersClass : IEnumerable<int>, IEnumerable, IEnumerator<int>, IDisposable, IEnumerator
 {
  public static Random r = new Random();

  /// <summary>
  ///   
  /// </summary>
  private int _state;

  /// <summary>
  ///     
  /// </summary>
  private int _current;

  /// <summary>
  ///   id
  /// </summary>
  private int _initialThreadId;

  /// <summary>
  ///       
  /// </summary>
  private int count;

  /// <summary>
  ///       
  /// </summary>
  public int _count;

  /// <summary>
  ///     
  /// </summary>
  private int i;

  int IEnumerator<int>.Current
  {
   [DebuggerHidden]
   get
   {
    return _current;
   }
  }

  object IEnumerator.Current
  {
   [DebuggerHidden]
   get
   {
    return _current;
   }
  }

  [DebuggerHidden]
  public GetRandomNumbersClass(int state)
  {
   this._state = state;
   _initialThreadId = Environment.CurrentManagedThreadId;
  }

  [DebuggerHidden]
  void IDisposable.Dispose()
  {
  }

  private bool MoveNext()
  {
   switch (_state)
   {
    default:
     return false;
    case 0:
     _state = -1;
     i = 0;
     break;
    case 1:
     _state = -1;
     i++;
     break;
   }
   if (i < count)
   {
    _current = r.Next(10);
    _state = 1;
    return true;
   }
   return false;
  }

  bool IEnumerator.MoveNext()
  {
   //ILSpy generated this explicit interface implementation from .override directive in MoveNext
   return this.MoveNext();
  }

  [DebuggerHidden]
  void IEnumerator.Reset()
  {
   throw new NotSupportedException();
  }

  [DebuggerHidden]
  public IEnumerator<int> GetEnumerator()
  {
   GetRandomNumbersClass _getRandom;
   if (_state == -2 && _initialThreadId == Environment.CurrentManagedThreadId)
   {
    _state = 0;
    _getRandom = this;
   }
   else
   {
    _getRandom = new GetRandomNumbersClass(0);
   }
   _getRandom.count = _count;
   return _getRandom;
  }

  [DebuggerHidden]
  IEnumerator IEnumerable.GetEnumerator()
  {
   return GetEnumerator();
  }


  [IteratorStateMachine(typeof(GetRandomNumbersClass))]
  private static IEnumerable<int> GetList(int count)
  {
   GetRandomNumbersClass getRandomNumbersClass = new GetRandomNumbersClass(-2);
   getRandomNumbersClass._count = count;
   return getRandomNumbersClass;
  }
  private static void Main(string[] args)
  {
   IEnumerator<int> enumerator = GetList(5).GetEnumerator();
   try
   {
    foreach (int item in GetList(5))
     Console.WriteLine(item);
    //while (enumerator.MoveNext())
    //{
    // int current = enumerator.Current;
    // Console.WriteLine(current);
    //}
   }
   finally
   {
    if (enumerator != null)
    {
     enumerator.Dispose();
    }
   }
   Console.ReadKey();
  }
 }
총결산
이상 은 이 글 의 모든 내용 입 니 다.본 고의 내용 이 여러분 의 학습 이나 업무 에 어느 정도 참고 학습 가 치 를 가지 기 를 바 랍 니 다.여러분 의 저희 에 대한 지지 에 감 사 드 립 니 다.

좋은 웹페이지 즐겨찾기