2012-02-08 4 views
4
foreach(var category in categories) { 
    a.AddRange(_db.Articles.Where(c => c.Categories.Contains(category))); 
} 

코드는 잘 실행, 아직 나는 람다 식에 사용 category 참조에서 "수정 폐쇄에 접근"에 대한 경고를 얻을.액세스

질문 :이 상황에서 어떤 경고가 표시됩니까?

+0

[이 관련 질문] (http://stackoverflow.com/questions/8898925/is-there-a-reason-for-cs-reuse-of-the-variable-in-a-foreach)을 참조하십시오. 도움이 될 수도 있습니다. –

+1

음, "수정 된 폐쇄 (Access to Modified Closure)"(http://stackoverflow.com/questions/235455/access-to-modified-closure) "에 대해 SO에 12 건의 안타가 있습니다.이 중 하나가이 질문에 대답합니다. –

+0

@ RaymondChen 거기에 있습니다,하지만 그들은 람다 컨텍스트를 해결하지 못했습니다 내가 물었습니다 유일한 이유입니다. 나는 closure의 개념을 이해하고,이 이상한 경우에 LINQ의 문맥에서 좀 더 구체적인 것을 의미 하는지를보고 싶었다. –

답변

6

경고는 Where 람다의 경우 변수 category에 액세스하기 때문에 발생합니다. 모든 반복마다 값이 category으로 변경되고 Where이 지연되므로 현재 람다가 작성되었을 때의 값과 비교하여 category의 현재 값이 표시됩니다.

이 경우에는 문제가 없습니다. Where이 지연 평가 되더라도 AddRange 메서드는 프롬프트이므로 Where의 평가가 완료됩니다. 따라서 Where 메서드는 예상 한 값인 category을 보게됩니다.

경고를 제거하려면 단순히 반복 변수의 로컬 복사본을 선언하고이를 대신 캡처하십시오.

foreach(var category in categories) { 
    var localCategory = category; 
    a.AddRange(_db.Articles.Where(c => c.Categories.Contains(localCategory))); 
} 
+0

foreach 루프에 대해 뭔가 잊어 버린 것 같습니다. 반복 변수'category'는 기술적으로 루프 오른쪽 밖에 있습니다. ? 이 의사 코드와 매우 흡사하다. int i; for (i = 10) {i ++; }'? 그렇다면 '범주'가 변경된 후'Where'가 평가 될 수 있다는 것을 이해합니다. 나는 정확하게 이해하고 있는가? –

+2

@ one.beat.consumer 맞습니다. – JaredPar

0

"category"변수는 클로저에 있으며 LINQ 표현식 외부에서 수정할 수 있음을 알려줍니다.

몇 가지 설명은 질문 here을보십시오.