문제
나는 그것이 무엇 인줄 안다 yield
몇 가지 예를 보았지만 실제 적용 사례가 생각나지 않습니다. 특정 문제를 해결하기 위해 이를 사용한 적이 있습니까?
(이상적으로는 다른 방법으로 해결할 수 없는 문제)
해결책
나는 이것이 오래된 질문이라는 것을 알고 있습니다(Jon Skeet 이전?). 그러나 나는 최근에 이 질문을 스스로 생각해 왔습니다.불행하게도 여기에 있는 현재 답변(제 생각에는)은 항복 설명의 가장 분명한 이점을 언급하지 않습니다.
Yield 문의 가장 큰 이점은 표준 목록을 사용하는 것보다 훨씬 더 효율적인 메모리 사용으로 매우 큰 목록을 반복할 수 있다는 것입니다.
예를 들어, 100만 개의 행을 반환하는 데이터베이스 쿼리가 있다고 가정해 보겠습니다.DataReader를 사용하여 모든 행을 검색하고 이를 List에 저장할 수 있으므로 list_size * row_size 바이트의 메모리가 필요합니다.
또는 Yield 문을 사용하여 Iterator를 생성하고 한 번에 하나의 행만 메모리에 저장할 수 있습니다.실제로 이는 대규모 데이터 세트에 대해 "스트리밍" 기능을 제공하는 기능을 제공합니다.
또한 Iterator를 사용하는 코드에서는 간단한 foreach 루프를 사용하고 필요에 따라 루프에서 벗어나도록 결정할 수 있습니다.일찍 중단하면(예를 들어) 처음 5개 행만 필요할 때 전체 데이터 세트를 강제로 검색하지 않은 것입니다.
에 관하여:
Ideally some problem that cannot be solved some other way
Yield 문은 사용자 정의 반복기 구현을 사용하여 수행할 수 없는 작업을 제공하지 않지만 필요한 복잡한 코드를 작성할 필요가 없도록 해줍니다.여러 가지 방법으로 해결할 수 없는 문제는 거의 없습니다.
다음은 더 자세한 내용을 제공하는 몇 가지 최근 질문과 답변입니다.
다른 팁
실제로 내 사이트에서는 비전통적인 방식으로 사용합니다. 아이디어파이프
public override IEnumerator<T> GetEnumerator()
{
// goes through the collection and only returns the ones that are visible for the current user
// this is done at this level instead of the display level so that ideas do not bleed through
// on services
foreach (T idea in InternalCollection)
if (idea.IsViewingAuthorized)
yield return idea;
}
따라서 기본적으로 아이디어 보기가 현재 승인되었는지 확인하고 승인된 경우 아이디어를 반환합니다.그렇지 않은 경우에는 그냥 건너뜁니다.이를 통해 아이디어를 캐시할 수 있지만 승인된 사용자에게 아이디어를 계속 표시할 수 있습니다.그렇지 않으면 1시간마다 순위가 다시 매겨지는 경우 권한에 따라 매번 다시 가져와야 합니다.
Enumerable 클래스의 LINQ 연산자는 항복 문을 사용하여 생성된 반복기로 구현됩니다.일반적으로 루프에서 열거자를 사용할 때까지 실제로 아무것도 열거하지 않고 Select() 및 Where()와 같은 작업을 연결할 수 있습니다. 각각 성명.또한 컬렉션 중간에 중지하기로 결정한 경우 IEnumerator.MoveNext()를 호출하면 하나의 값만 계산되므로 모든 결과 계산에 따른 성능 저하를 줄일 수 있습니다.
반복자는 필요할 때만 표현식이 평가되는 다른 종류의 지연 평가를 구현하는 데에도 사용할 수 있습니다.당신은 또한 사용할 수 있습니다 생산하다 코루틴과 같은 더 멋진 것들을 위해.
Yield의 또 다른 좋은 용도는 IEnumerable의 요소에 대해 함수를 수행하고 다른 유형의 결과를 반환하는 것입니다. 예를 들면 다음과 같습니다.
public delegate T SomeDelegate(K obj);
public IEnumerable<T> DoActionOnList(IEnumerable<K> list, SomeDelegate action)
{
foreach (var i in list)
yield return action(i);
}
Yield를 사용하면 구체적인 유형으로 다운캐스팅되는 것을 방지할 수 있습니다.이는 컬렉션 소비자가 컬렉션을 조작하지 못하도록 하는 데 유용합니다.
당신은 또한 사용할 수 있습니다 yield return
일련의 함수 결과를 목록으로 처리합니다.예를 들어 직원들에게 2주마다 급여를 지급하는 회사를 생각해 보세요.다음 코드를 사용하면 급여 날짜의 하위 집합을 목록으로 검색할 수 있습니다.
void Main()
{
var StartDate = DateTime.Parse("01/01/2013");
var EndDate = DateTime.Parse("06/30/2013");
foreach (var d in GetPayrollDates(StartDate, EndDate)) {
Console.WriteLine(d);
}
}
// Calculate payroll dates in the given range.
// Assumes the first date given is a payroll date.
IEnumerable<DateTime> GetPayrollDates(DateTime startDate, DateTime endDate, int daysInPeriod = 14) {
var thisDate = startDate;
while (thisDate < endDate) {
yield return thisDate;
thisDate = thisDate.AddDays(daysInPeriod);
}
}