문제

나는 C#을 배우고 있었고 Lambdas를 이해하려고 노력하고 있습니다. 아래 샘플에서 10 번 10 번 인쇄합니다.

class Program
{
    delegate void Action();
    static void Main(string[] args)
    {
        List<Action> actions = new List<Action>();

        for (int i = 0; i < 10; ++i )
            actions.Add(()=>Console.WriteLine(i));

        foreach (Action a in actions)
            a();
    }
}

분명히, 람다 뒤에 생성 된 클래스는 int i 변수이며 루프가 반복 될 때마다 동일한 참조에 새 값을 할당합니다. C ++ 0x 구문과 같이 Lamda가 대신 사본을 잡도록 강제하는 방법이 있습니까?

[&](){ ... } // Capture by reference

vs.

[=](){ ... } // Capture copies
도움이 되었습니까?

해결책

컴파일러가하는 일은 람다와 람다에서 캡처 한 변수를 컴파일러 생성 중첩 클래스로 끌어 당기는 것입니다.

편집 후 예제는 다음과 같이 보입니다.

class Program
{
        delegate void Action();
        static void Main(string[] args)
        {
                List<Action> actions = new List<Action>();

                DisplayClass1 displayClass1 = new DisplayClass1();
                for (displayClass1.i = 0; displayClass1.i < 10; ++displayClass1.i )
                        actions.Add(new Action(displayClass1.Lambda));

                foreach (Action a in actions)
                        a();
        }

        class DisplayClass1
        {
                int i;
                void Lambda()
                {
                        Console.WriteLine(i);
                }
        }
}

For Loop 내에서 사본을 만들어 컴파일러는 각 반복에서 다음과 같이 새 개체를 생성합니다.

for (int i = 0; i < 10; ++i)
{
    DisplayClass1 displayClass1 = new DisplayClass1();
    displayClass1.i = i;
    actions.Add(new Action(displayClass1.Lambda));
}

다른 팁

내가 찾을 수있는 유일한 해결책은 먼저 로컬 사본을 만드는 것입니다.

for (int i = 0; i < 10; ++i)
{
    int copy = i;
    actions.Add(() => Console.WriteLine(copy));
}

그러나 나는 For-loop 안에 사본을 넣는 이유를 이해하는 데 어려움을 겪고 있습니다. i.

유일한 해결책은 Lambda 내에서 로컬 사본을 만들고 참조하는 것입니다. 클로저에서 액세스 할 때 C# (및 vb.net)의 모든 변수는 참조 시맨틱과 카피/값 의미를 갖습니다. 이 동작을 어느 언어로도 바꿀 방법이 없습니다.

참고 : 실제로 참조로 컴파일하지 않습니다. 컴파일러는 변수를 클로저 클래스로 들어 올리고 주어진 폐쇄 클래스 내부의 "I"의 "I"에 대한 액세스를 "I"로 리디렉션합니다. 그래도 참조 의미로 생각하는 것이 종종 더 쉽습니다.

람다 표현은 실제로 익명의 방법에 대한 구문 설탕 일뿐입니다.

즉, 당신이 실제로 찾고있는 것은 익명의 방법이 부모의 범위에서 로컬 변수를 사용하는 방법입니다.

다음은 이것을 설명하는 링크입니다. http://www.codeproject.com/kb/cs/insideanonymousmethods.aspx#4

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top