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();
}
}
총결산이상 은 이 글 의 모든 내용 입 니 다.본 고의 내용 이 여러분 의 학습 이나 업무 에 어느 정도 참고 학습 가 치 를 가지 기 를 바 랍 니 다.여러분 의 저희 에 대한 지지 에 감 사 드 립 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
C#Task를 사용하여 비동기식 작업을 수행하는 방법라인이 완성된 후에 이 라인을 다시 시작할 수 없습니다.반대로 조인(Join)만 결합할 수 있습니다 (프로세스가 현재 라인을 막습니다). 임무는 조합할 수 있는 것이다. 연장을 사용하여 그것들을 한데 연결시키는 것이...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.