클로저의 변수 캡처에 대한 자세한 설명
변수 캡처가 클로저 생성을 위해 변수를 가져 오는 방법에 대한 수많은 게시물을 보았지만, 모두 특정 세부 사항이 부족하고 모든 것을 "컴파일러 마법"이라고 부르는 것 같습니다.
다음에 대한 명확한 설명을 찾고 있습니다.
- 지역 변수가 실제로 캡처되는 방법.
- 값 유형 캡처와 참조 유형 간의 차이 (있는 경우)
- 그리고 값 유형과 관련하여 권투가 발생하는지 여부.
내가 선호하는 것은 가치와 포인터 (내부적으로 일어나는 일의 핵심에 더 가깝다) 측면에서 대답하는 것이지만, 가치와 참조를 포함하는 명확한 대답도 받아 들일 것입니다.
- 까다 롭습니다. 잠시 후에 그것에 올 것입니다.
- 차이는 없습니다. 두 경우 모두 캡처되는 변수 자체입니다.
- 아니, 권투가 발생하지 않습니다.
예제를 통해 캡처가 어떻게 작동하는지 보여주는 것이 가장 쉬울 것입니다.
다음은 단일 변수를 캡처하는 람다 식을 사용하는 코드입니다.
using System;
class Test
{
static void Main()
{
Action action = CreateShowAndIncrementAction();
action();
action();
}
static Action CreateShowAndIncrementAction()
{
Random rng = new Random();
int counter = rng.Next(10);
Console.WriteLine("Initial value for counter: {0}", counter);
return () =>
{
Console.WriteLine(counter);
counter++;
};
}
}
이제 컴파일러가 수행하는 작업이 있습니다. 단, C #에서는 실제로 발생할 수없는 "말할 수없는"이름을 사용합니다.
using System;
class Test
{
static void Main()
{
Action action = CreateShowAndIncrementAction();
action();
action();
}
static Action CreateShowAndIncrementAction()
{
ActionHelper helper = new ActionHelper();
Random rng = new Random();
helper.counter = rng.Next(10);
Console.WriteLine("Initial value for counter: {0}", helper.counter);
// Converts method group to a delegate, whose target will be a
// reference to the instance of ActionHelper
return helper.DoAction;
}
class ActionHelper
{
// Just for simplicity, make it public. I don't know if the
// C# compiler really does.
public int counter;
public void DoAction()
{
Console.WriteLine(counter);
counter++;
}
}
}
루프에서 선언 된 변수를 캡처하면 루프의 ActionHelper
각 반복마다 의 새 인스턴스가 생성 되므로 변수의 서로 다른 "인스턴스"를 효과적으로 캡처 할 수 있습니다.
다른 범위에서 변수를 캡처 할 때 더 복잡해집니다. 그런 수준의 세부 정보를 정말로 원하는지 알려주세요. 아니면 코드를 작성하고 Reflector에서 디 컴파일 한 다음 따라 해보세요. :)
방법에 유의하십시오.
- 관련된 권투가 없습니다
- There are no pointers involved, or any other unsafe code
EDIT: Here's an example of two delegates sharing a variable. One delegate shows the current value of counter
, the other increments it:
using System;
class Program
{
static void Main(string[] args)
{
var tuple = CreateShowAndIncrementActions();
var show = tuple.Item1;
var increment = tuple.Item2;
show(); // Prints 0
show(); // Still prints 0
increment();
show(); // Now prints 1
}
static Tuple<Action, Action> CreateShowAndIncrementActions()
{
int counter = 0;
Action show = () => { Console.WriteLine(counter); };
Action increment = () => { counter++; };
return Tuple.Create(show, increment);
}
}
... and the expansion:
using System;
class Program
{
static void Main(string[] args)
{
var tuple = CreateShowAndIncrementActions();
var show = tuple.Item1;
var increment = tuple.Item2;
show(); // Prints 0
show(); // Still prints 0
increment();
show(); // Now prints 1
}
static Tuple<Action, Action> CreateShowAndIncrementActions()
{
ActionHelper helper = new ActionHelper();
helper.counter = 0;
Action show = helper.Show;
Action increment = helper.Increment;
return Tuple.Create(show, increment);
}
class ActionHelper
{
public int counter;
public void Show()
{
Console.WriteLine(counter);
}
public void Increment()
{
counter++;
}
}
}
ReferenceURL : https://stackoverflow.com/questions/5438307/detailed-explanation-of-variable-capture-in-closures
'Development Tip' 카테고리의 다른 글
jquery는 레일 표준 REST DELETE 응답에 대해 $ .ajax에서 성공 메서드를 호출하지 않습니다. (0) | 2020.12.25 |
---|---|
jsonp 콘텐츠 유형으로 jQuery.ajax 요청 후 parsererror (0) | 2020.12.25 |
JavaScript의 구성, 상속 및 집계 (0) | 2020.12.25 |
내 jQuery : not () 선택기가 CSS에서 작동하지 않는 이유는 무엇입니까? (0) | 2020.12.25 |
Java에서 Base64 문자열 디코딩 (0) | 2020.12.25 |