2009-05-12 3 views
4

C# 값을 Lambdas에 전달합니까? 나는 몇 가지 코드를

int count = 0; 

list.ForEach(i => i.SomeFunction(count++)); 

이 수를 증가하지 보인다. 여기서 가치는 가치로 전달됩니까? 람다에서 {}을 사용하면 어떤 차이가 있습니까?

int count = 0; 

list.ForEach(i => 
      { 
        i.SomeFunction(count++); 
      }); 

업데이트 1

죄송합니다, 내 실수는, 원래 카운트를 업데이트한다.

+0

나는 당신이 그들을 사용하는 동시에 변수 수정에 대한 조언, 그것은 당신에게 많은 입력을 저장하지 않고 문제의 끝이 발생할 수 있습니다. –

답변

6

count은 int이고 int는 값 유형이므로 실제로 값으로 전달됩니다. 첫 번째 예제와 두 번째 예제 간에는 의미 적 차이가 없습니다.

(말하자면, 원래의 참조를 클로저까지 캡처해야하기 때문에 count이 증가해야하는 것처럼 보입니다. 명확히하기 위해 Count가 값에 의해 SomeFunction으로 전달되지만, 표현식 안에서 사용할 때 람다 표현식에 "전달"됩니다. 외부 표현식과 동일한 참조입니다.

0

아니요, 차이는 없습니다. 인수는 람다에 사용되는 델리게이트 정의에서 명시 적으로 "ref"또는 "out"으로 지정하지 않는 한 일반적으로 값을 사용합니다.

1

이렇게하면 카운트 값을 closure으로 캡처해야합니다.

0

람다는 익명 함수이므로 인수를 함수로 전달할 때와 동일한 규칙을 따릅니다.

+0

캡처 된 변수는 매우 다른 규칙을 따릅니다 ... –

5

두 경우 모두 클로저라는 것을 만들고 있습니다. 본질적으로, count는 클래스에서 래핑되고 그 클래스는 람다 표현식에 의해 사용되고있다.

빌 바그너 (Bill Wagner)는 More Effective C#이라는 훌륭한 책을 보유하고 있으며 그는 closures을 자세히 설명하는 블로그 게시물을 보유하고 있습니다. 증가한다

4

, 증거 :

class Foo 
{ 
    public void SomeFunction(int i) { } 
} 
static void Main() 
{ 
    int count = 0; 
    List<Foo> list = new List<Foo> {new Foo()}; 
    list.ForEach(i => i.SomeFunction(count++)); 
    Console.WriteLine(count); // 1 
} 

람다 행위는 (이미 언급 한 바와 같이) "캡처"본질적으로 같은 코드를 만들고, 계산하기 :

class Foo 
{ 
    public void SomeFunction(int i) { } 
} 
class CaptureScope 
{ 
    public int count; 
    public void AnonMethod(Foo foo) 
    { 
     foo.SomeFunction(count++); 
    } 
} 
static void Main() 
{ 
    CaptureScope scope = new CaptureScope(); 
    scope.count = 0; 
    List<Foo> list = new List<Foo> {new Foo()}; 
    list.ForEach(scope.AnonMethod); 
    Console.WriteLine(scope.count); // 1 
} 

위의 대략적인 근사치 컴파일러가 델리게이트 람다를 해석하는 방법 보시다시피, count은 클래스의 필드이고 입니다.

0

이 경우 count 변수는 이고입니다. struct 일지라도 캡처 된 변수는 참조처럼 작동합니다. 따라서 foreach 다음에 증가 된 count이 표시됩니다.

5

변수 카운트는 상황에 따라 람다 식으로 캡처됩니다. count의 변경 사항은 발신자에게 표시됩니다.그래서, 예를 들면 : 각 반복에 당신이 count을 증가하고 있기 때문에

int count = 0; 
list.ForEach(i => i.SomeFunction(count++)); 
Console.WriteLine(count); 

는 목록의 크기를 표시합니다.

그러나 SomeFunction 호출이 SomeFunction 가치 의해 count++의 평가 값 (증분 전의 count의 값) 통과한다. 즉, SomeFunctioncount의 값을 변경할 수 없습니다.

클로저 및 변수 캡처에 대한 자세한 내용은 내 closures article을 참조하십시오.

3

여기에 작은 수정 사항을 추가하고 싶습니다. 변수 수는 값이 아니거나 매개 변수가 아니기 때문에 람다 식에 대한 참조로 전달되지 않습니다. 이 값은 대신 으로 캡쳐 된입니다.

당신은 주제에 레이몬드의 시리즈를 체크 아웃해야합니다 - http://blogs.msdn.com/oldnewthing/archive/2006/08/02/686456.aspx

관련 문제