2011-08-29 5 views
3

편집 "는 람다 식에 반복 변수를 사용하여 예기치 않은 결과를 가질 수있다"경고 :

Dim numbers1 As New List(Of Int32)({1, 2, 3}) 
Dim numbers2 As New List(Of Int32)({3, 4, 5}) 
For Each n1 In numbers1 
    ' no warning ' 
    Dim contains = numbers2.Contains(n1) 
Next 
For Each n1 In numbers1 
    ' warning on n1' 
    Dim contains = (From num In numbers2 Where num = n1).Any 
Next 

: 다음은이 문제를 (내가 deleted 내 원래의 질문을했습니다) 훨씬 더 간단한 예입니다 그래서 저는 컴파일러가 왜 두 번째 반복에서 예상치 못한 결과를 얻을 수 있다고 생각하는지 이해하지 못합니다. 반면에 처음에는 안전합니다. 나는 @ ee-m의 interesting link이이 동작에 대한 이유를 제공하지 않는다고 생각한다. (for-each 이슈가 아니기 때문에 For n1 As Int32 = 1 To 3도 컴파일러 경고가된다.)

내가 다음은 "모범 사례"를해야한다고 정말 확신 아니에요 :

For Each n1 In numbers1 
    Dim number1 = n1 
    ' no warning' 
    Dim contains = (From num In numbers2 Where num = number1).Any 
Next 

지역 변수 number1가 중복 및 메타 나이트가 이미 강조했다 @ 덜 읽을 수있는 코드를합니다. 참고 : 세 가지 방법 모두 안전하며 올바른 결과를 제공합니다.

답변

3

메시지에 말한대로 원치 않는 결과가있을 수 있습니다. 귀하의 경우에는 .ToList()가 안전하지만 컴파일러가 확인하기가 어렵습니다.

에릭 Lippert의가 (코드 예제는 C#에서 VB 없음) 진행되는이 주제에 대한 블로그 게시물의 몇 가지를 썼다

+0

왜 하드 컴파일러가 확인이 가능합니까? LINQ-Query는'ToList'가 문맥 밖이므로 LINQ-Query가 즉시 실행된다는 것을 알 수 없습니다. 그러나 반복 변수는 이미이 시점에서 실행 되었기 때문에 변경할 수 없습니다. 나는 컴파일러가 이것을 알고 있다고 가정하고, 반복 변수를 쿼리에 "하드 할당"할 수 있습니다. 하지만 당신의 제안을 지역 변수에 복사하기 위해 채택했습니다. –

+0

컴파일러 빌더의 _Why_ 부분 ID. 그러나 얼마나 멀리 되돌아 가야합니까? 여기서는 AllExcelFiles가 List (Of T)이지만 일반적으로 IEnumerable (Of T)이 될 것입니다. 나는 경고 -goo가 ForEach의 범위가 제한되어 있다고 생각합니다. –

+1

이 문제는 "Dim exc = excel"행이 완전히 불필요하고 코드가 덜 명확 해져서 실제로 이것을 "모범 사례"라고 부를 수 있는지 여부를 알 수 없습니다. 나는이 경고 메시지를 직접 억지로 생각하고있다. 왜냐하면이 경우와 같이 많은 가양 성이 있기 때문이다. –

4

표준 '모범 사례'와 같은 로컬 VAR (Dim exc = excel)에 복사를 채택하도록 제안 흥미로운 찾을 수 있습니다 코드의 종류에서 발생할 수있는 "개는"일부 이상 :

Closing over the loop variable considered harmful

+1

정말 재미 있습니다. C#에는 그러한 경고가 없습니다. Lippert의 말 : "올바른 행동에 대해 경고하는 경고는 매우 나쁜 경고입니다." –

+0

+1 흥미로운 링크. 어쩌면 내가 eric의 요점을 오해 했습니다만, for-each 루프를 'For n1 As Int32 = 1 To 3'으로 바꾸더라도 문제는 동일합니다. 그런 다음 [변수의 범위가 루프의 본문이되어서는 안됩니다] (http://msdn.microsoft.com/en-us/library/5z06z1kb.aspx#Y2554)? –

+0

@Tim Schmelter : for 루프에 대해서도 똑같은 문제가 발생합니다. C#과 VB에는 차이점이 있습니다. VB에서는 루프 밖에서 루프 변수를 참조 할 수 없습니다. 그러나 이것은 동일한 변수가 반복에서 다음으로 재사용된다는 사실을 변경하지 않습니다. –