폐쇄 란 무엇입니까?


155

때때로 나는 "폐쇄 물"이 언급되는 것을보고, 그것을 찾아 보려고 시도했지만 Wiki는 내가 이해하고있는 설명을하지 않았다. 누군가 나를 도와 줄 수 있습니까?


Java / C #을 알고 있다면이 링크가 도움이 될 것입니다. http://www.developerfusion.com/article/8251/the-beauty-of-closures/
Gulshan

1
클로저는 이해하기 어렵다. 해당 Wikipedia 기사의 첫 번째 문장에있는 모든 링크를 클릭하고 해당 기사를 먼저 이해해야합니다.
Zach


3
클로저와 클래스의 근본적인 차이점은 무엇입니까? 좋아, 공개 메소드가 하나 뿐인 클래스.
biziclop

5
@biziclop : 클래스로 클로저를 에뮬레이션 할 수 있습니다 (Java 개발자가 해야하는 일). 그러나 그것들은 일반적으로 생성하기에 약간 덜 장황하고 당신이 돌보는 것을 수동으로 관리 할 필요가 없습니다. (하드 코어리스 퍼도 비슷한 질문을하지만, 다른 결론에 도달 할 가능성이있다. 폐쇄시 언어 수준의 OO 지원은 불필요하다).

답변:


141

(면책 조항 : 이것은 기본적인 설명입니다. 정의가있는 한, 조금 단순화하고 있습니다)

클로저를 생각하는 가장 간단한 방법 은 변수 ( "일류 함수"라고 함)로 저장 될 수 있는 함수이며 ,이 변수는 작성된 범위 내에서 다른 변수에 액세스 할 수있는 특별한 기능을 가지고 있습니다.

예 (자바 스크립트) :

var setKeyPress = function(callback) {
    document.onkeypress = callback;
};

var initialize = function() {
    var black = false;

    document.onclick = function() {
        black = !black;
        document.body.style.backgroundColor = black ? "#000000" : "transparent";
    }

    var displayValOfBlack = function() {
        alert(black);
    }

    setKeyPress(displayValOfBlack);
};

initialize();

기능 1 에 할당 document.onclick하고는 displayValOfBlack폐쇄된다. 둘 다 부울 변수를 참조 black하지만 해당 변수가 함수 외부에 할당되어 있음을 알 수 있습니다. 왜냐하면 black함수가 정의 된 범위에 국부적으로 ,이 변수에 대한 포인터는 보존된다.

이것을 HTML 페이지에 넣으면 :

  1. 검은 색으로 변경하려면 클릭
  2. "참"을 보려면 [입력]을 누르십시오
  3. 다시 클릭하면 흰색으로 다시 바뀝니다.
  4. "false"를 보려면 [enter]를 누르십시오

이것은 둘 다 same에 액세스 할 black수 있으며 랩퍼 오브젝트 없이 상태를 저장하는 데 사용될 수 있음을 보여줍니다 .

에 대한 호출 setKeyPress은 어떤 변수처럼 함수를 전달할 수 있는지 보여줍니다. 범위 폐쇄 보존 여전히 함수가 정의 된 하나이다.

클로저는 일반적으로 이벤트 핸들러, 특히 JavaScript 및 ActionScript에서 사용됩니다. 클로저를 잘 사용하면 객체 래퍼를 만들지 않고도 변수를 이벤트 핸들러에 암시 적으로 바인딩 할 수 있습니다. 그러나 부주의하게 사용하면 메모리 누수가 발생합니다 (예 : 사용되지 않지만 보존 된 이벤트 핸들러가 메모리의 큰 오브젝트, 특히 DOM 오브젝트를 보유하여 가비지 콜렉션을 방지하는 유일한 경우).


1 : 실제로 JavaScript의 모든 함수는 클로저입니다.


3
나는 당신의 대답을 읽으면서 전구가 떠오르는 것을 느꼈습니다. 매우 감사! :)
Jay

1
때문에 black함수 내에서 선언 된 스택이 풀릴, 그이 ... 파괴되지 것?
gablin

1
@gablin, 이것이 클로저가있는 언어의 독특한 점입니다. 가비지 콜렉션이있는 모든 언어는 거의 같은 방식으로 작동합니다. 오브젝트에 대한 참조가 더 이상 없으면 파괴 될 수 있습니다. JS에서 함수가 생성 될 때마다 해당 함수가 소멸 될 때까지 로컬 범위가 해당 함수에 바인딩됩니다.
Nicole

2
@gablin, 좋은 질문입니다. 나는 그들이 & mdash 를 할 수 없다고 생각 합니다; 그러나 JS가 사용하는 것과 가비지 콜렉션을 가져 왔기 때문에 " black함수 안에 선언되었으므로 파괴되지 않을 것 "이라고 말했을 때 참조한 것 같습니다 . 함수에서 객체를 선언 한 다음 다른 곳에 존재하는 변수에 할당하면 해당 객체에 대한 다른 참조가 있기 때문에 해당 객체가 유지된다는 점을 기억하십시오.
Nicole

1
Objective-C (및 Clang의 C)는 가비지 콜렉션없이 본질적으로 클로저 인 블록을 지원합니다. 런타임 지원 및 메모리 관리에 대한 수동 개입이 필요합니다.
quixoto

68

클로저는 기본적으로 객체를 보는 다른 방법입니다. 객체는 하나 이상의 함수가 바인딩 된 데이터입니다. 클로저는 하나 이상의 변수가 바인딩 된 함수입니다. 둘은 구현 수준에서 최소한 기본적으로 동일합니다. 실제 차이점은 어디에서 왔는지에 있습니다.

객체 지향 프로그래밍에서는 멤버 변수와 메서드 (멤버 함수)를 미리 정의하여 객체 클래스를 선언 한 다음 해당 클래스의 인스턴스를 만듭니다. 각 인스턴스에는 생성자에 의해 초기화 된 멤버 데이터의 사본이 제공됩니다. 그런 다음 객체 유형의 변수가 있고 데이터의 성격에 중점을두기 때문에 데이터로 전달합니다.

반면 클로저에서는 객체가 객체 클래스처럼 미리 정의되거나 코드에서 생성자 호출을 통해 인스턴스화되지 않습니다. 대신 클로저를 다른 함수 내부의 함수로 작성합니다. 클로저는 외부 함수의 로컬 변수를 참조 할 수 있으며 컴파일러는이를 감지하여 이러한 변수를 외부 함수의 스택 공간에서 클로저의 숨겨진 개체 선언으로 이동합니다. 그런 다음 클로저 유형의 변수가 있으며 기본적으로 후드 아래의 객체이지만 포커스는 그 특성에 초점을 맞추기 때문에 함수 참조로 전달합니다.


3
+1 : 좋은 답변입니다. 하나의 메소드 만있는 객체로 클로저를 볼 수 있으며, 임의의 객체는 일반적인 기본 데이터 (객체의 멤버 변수)에 대한 클로저 컬렉션으로 볼 수 있습니다. 이 두 가지 견해는 상당히 대칭 적이라고 생각합니다.
Giorgio

3
아주 좋은 대답입니다. 실제로 폐쇄에 대한 통찰력을 설명합니다.
RoboAlex

1
@Mason Wheeler : 클로저 데이터는 어디에 저장됩니까? 함수처럼 스택에? 아니면 물건처럼 힙에 있습니까?
RoboAlex

1
@RoboAlex : 힙에서 함수 처럼 보이는 객체이기 때문 입니다.
메이슨 휠러

1
@RoboAlex : 클로저 및 캡처 된 데이터가 저장되는 위치는 구현에 따라 다릅니다. C ++에서는 힙이나 스택에 저장할 수 있습니다.
조르지오

29

클로저 라는 용어 는 코드 조각 (블록, 함수) 이 코드 블록이 정의 된 환경에 의해 닫히는 (즉, 값에 바인딩 된) 자유 변수를 가질 수 있다는 사실에서 비롯 됩니다.

예를 들어 스칼라 함수 정의를 보자.

def addConstant(v: Int): Int = v + k

함수 본문에는 두 개의 이름 (변수)이 v있으며 k두 개의 정수 값을 나타냅니다. 이름 v은 함수의 인수로 선언되기 때문에 바인딩됩니다 addConstant(함수 선언 v시 함수 호출시 값이 할당 됨을 알 수 있습니다). k함수 addConstant에 어떤 값 k이 바인딩되는지 (및 방법)에 대한 실마리가 포함되어 있지 않기 때문에 이름 은 함수에서 자유 입니다.

다음과 같은 호출을 평가하려면 다음을 수행하십시오.

val n = addConstant(10)

k이름 k이 정의 된 컨텍스트에 정의 된 경우에만 발생할 수있는 값 을 지정해야합니다 addConstant. 예를 들면 다음과 같습니다.

def increaseAll(values: List[Int]): List[Int] =
{
  val k = 2

  def addConstant(v: Int): Int = v + k

  values.map(addConstant)
}

이제 우리는 정의 addConstant된 컨텍스트에서 k정의 했으므로 모든 자유 변수가 이제 닫혀 있기 때문에 클로저addConstant 가되었습니다 (값에 바인딩 됨). 마치 함수처럼 호출되고 전달 될 수 있습니다. 자유 변수 는 클로저가 정의 될 때 값에 바인딩되는 반면 인수 변수 는 클로저가 호출 될 때 바인딩 됩니다 .addConstantkv

따라서 클로저는 기본적으로 컨텍스트에 의해 바인딩 된 후 자유 변수를 통해 로컬이 아닌 값에 액세스 할 수있는 함수 또는 코드 블록입니다.

많은 언어에서 클로저를 한 번만 사용하면 익명으로 만들 수 있습니다 ( 예 :

def increaseAll(values: List[Int]): List[Int] =
{
  val k = 2

  values.map(v => v + k)
}

자유 변수가없는 함수는 빈 경우 (빈 자유 변수 세트가있는) 특수한 경우입니다. 마찬가지로 익명 함수익명 클로저 의 특별한 경우입니다. 즉, 익명 함수는 자유 변수가없는 익명 클로저입니다.


이것은 논리에서 닫힌 공식과 열린 공식과 잘 어울립니다. 답변 주셔서 감사합니다.
RainDoctor

@RainDoctor : 자유 변수는 논리 수식과 람다 미적분 식에서 비슷한 방식으로 정의됩니다. 람다 식의 람다는 논리 수식의 자유 / 결합 변수의 수량 자처럼 작동합니다.
조르지오

9

JavaScript의 간단한 설명 :

var closure_example = function() {
    var closure = 0;
    // after first iteration the value will not be erased from the memory
    // because it is bound with the returned alertValue function.
    return {
        alertValue : function() {
            closure++;
            alert(closure);
        }
    };
};
closure_example();

alert(closure)이전에 생성 된 값을 사용합니다 closure. 반환 된 alertValue함수의 네임 스페이스는 closure변수 가있는 네임 스페이스에 연결됩니다 . 전체 함수를 삭제하면 closure변수 값 이 삭제되지만 그때까지 alertValue함수는 항상 variable 값을 읽고 쓸 수 있습니다 closure.

이 코드를 실행하면 첫 번째 반복에서 값 0을 closure변수에 할당 하고 함수를 다음과 같이 다시 작성합니다.

var closure_example = function(){
    alertValue : function(){
        closure++;
        alert(closure);
    }       
}

함수를 실행 alertValue하려면 로컬 변수 closure가 필요 하기 때문에 이전에 할당 된 로컬 변수의 값과 자신을 바인딩합니다 closure.

이제 closure_example함수 를 호출 할 때마다 바인딩 된 closure변수 의 증분 값을 씁니다 alert(closure).

closure_example.alertValue()//alerts value 1 
closure_example.alertValue()//alerts value 2 
closure_example.alertValue()//alerts value 3
//etc. 

고마워, 나는 코드를 테스트하지 않았다 =) 이제 모든 것이 좋아 보인다.
Muha

5

"클로저"는 본질적으로 패키지에 결합 된 일부 로컬 상태 및 코드입니다. 일반적으로 로컬 상태는 주변 (어휘) 범위에서 나오며 코드는 본질적으로 내부 함수이며 외부로 반환됩니다. 그러면 클로저는 내부 함수가 보는 캡처 된 변수와 내부 함수의 코드의 조합입니다.

불행히도 익숙하지 않기 때문에 설명하기가 어려운 것들 중 하나입니다.

제가 과거에 성공적으로 사용한 한 유추는 "우리가 '책'이라고 부르는 것을 상상해보십시오. 방을 닫을 때 '책'은 TAOCP의 모퉁이, 탁자에 있습니다. , 그것은 드레스덴 파일 책의 사본입니다. 따라서 폐쇄 된 내용에 따라 '책을주세요'라는 코드로 인해 다른 일이 발생합니다. "


: 당신이 잊어 en.wikipedia.org/wiki/Closure_(computer_programming을) 당신의 대답에.
S.Lott

3
아니요, 해당 페이지를 닫지 않기로 결정했습니다.
Vatine

"상태 및 함수": static지역 변수가 있는 C 함수를 클로저로 간주 할 수 있습니까? Haskell의 폐쇄는 국가와 관련이 있습니까?
Giorgio

2
Haskell의 @Giorgio Closures는 그들이 정의한 어휘 범위의 논증에 대해 결론을 내린다. 그래서 나는 "yes"라고 말할 것이다. 정적 변수가있는 AC 함수는 기껏해야 매우 제한된 클로저입니다 ( static로컬 변수를 사용하면 단일 함수에서 여러 클로저를 만들 수 있기를 정말로 원합니다 ).
Vatine

정적 변수가있는 C 함수는 클로저가 아니라고 생각하기 때문에 의도적 으로이 질문을했습니다. 정적 변수는 로컬로 정의되어 있으며 클로저 내부에서만 알려져 있으며 환경에 액세스하지 않습니다. 또한 100 % 확신 할 수는 없지만 다른 방법으로 진술을 공식화합니다. 폐쇄 메커니즘을 사용하여 다른 함수를 만듭니다 (함수는 클로저 정의 + 자유 변수에 대한 바인딩입니다).
Giorgio

5

'상태'의 개념을 정의하지 않고 폐쇄가 무엇인지 정의하는 것은 어렵습니다.

기본적으로 함수를 일급 값으로 취급하는 완전한 어휘 범위가있는 언어에서는 특별한 일이 발생합니다. 내가 다음과 같은 일을해야한다면 :

function foo(x)
return x
end

x = foo

변수 x는 참조 function foo()뿐만 아니라 foo마지막에 반환 된 상태를 참조합니다 . 실제 마술 foo은 다른 기능이 그 범위 내에서 더 정의 될 때 발생합니다 . 그것은 자체 미니 환경과 같습니다 (글로벌 환경에서 함수를 정의하는 '일반적으로'와 같습니다).

기능적으로 여러 함수 호출에서 로컬 변수의 상태를 유지하는 C ++ (C?)의 'static'키워드와 동일한 많은 문제를 해결할 수 있습니다. 그러나 함수는 일급 값이므로 동일한 원리 (정적 변수)를 함수에 적용하는 것과 비슷합니다. 클로저는 전체 함수의 상태가 저장 될 수 있도록 지원합니다 (C ++의 정적 함수와는 무관).

함수를 일급 값으로 취급하고 클로저에 대한 지원을 추가한다는 것은 메모리에 같은 클래스의 인스턴스가 둘 이상있을 수 있음을 의미합니다 (클래스와 유사). 이것이 의미하는 것은 함수 내에서 C ++ 정적 변수를 다룰 때 필요한 것처럼 함수의 상태를 재설정하지 않고도 동일한 코드를 재사용 할 수 있다는 것입니다 (이것에 대해 잘못된 것일 수 있습니다).

다음은 Lua의 클로저 지원 테스트입니다.

--Closure testing
--By Trae Barlow
--

function myclosure()
    print(pvalue)--nil
    local pvalue = pvalue or 10
    return function()
        pvalue = pvalue + 10 --20, 31, 42, 53(53 never printed)
        print(pvalue)
        pvalue = pvalue + 1 --21, 32, 43(pvalue state saved through multiple calls)
        return pvalue
    end
end

x = myclosure() --x now references anonymous function inside myclosure()

x()--nil, 20
x() --21, 31
x() --32, 42
    --43, 53 -- if we iterated x() again

결과 :

nil
20
31
42

까다로울 수 있으며 언어마다 다를 수 있지만 루아에서는 함수가 실행될 때마다 상태가 재설정되는 것으로 보입니다. 나는 우리가 myclosure함수 / 상태에 직접 액세스한다면 (익명 함수를 통해 반환하지 않고) pvalue10으로 다시 재설정 되는 경우 위 코드의 결과가 다르기 때문에 이것을 말한다 . 그러나 x (익명 함수)를 통해 myclosure의 상태에 액세스하면 pvalue메모리의 어딘가에 살아 있음을 알 수 있습니다 . 나는 그것에 조금 더 있다고 생각합니다. 아마도 누군가 구현의 본질을 더 잘 설명 할 수 있습니다.

추신 : 나는 C ++ 11 (이전 버전의 것 이외)을 핥지 못하므로 이것이 C ++ 11과 Lua의 클로저 사이의 비교가 아니라는 점에 유의하십시오. 또한 Lua에서 C ++ 로의 모든 '라인'은 정적 변수와 클로저가 100 % 동일하지 않기 때문에 유사합니다. 그것들이 때때로 비슷한 문제를 해결하는데 사용 되더라도.

내가 확실하지 않은 것은 위의 코드 예제에서 익명 함수 또는 상위 함수가 클로저로 간주되는지 여부입니다.


4

클로저는 상태가 관련된 함수입니다.

펄에서는 다음과 같이 클로저를 만듭니다.

#!/usr/bin/perl

# This function creates a closure.
sub getHelloPrint
{
    # Bind state for the function we are returning.
    my ($first) = @_;a

    # The function returned will have access to the variable $first
    return sub { my ($second) = @_; print  "$first $second\n"; };
}

my $hw = getHelloPrint("Hello");
my $gw = getHelloPrint("Goodby");

&$hw("World"); // Print Hello World
&$gw("World"); // PRint Goodby World

C ++에서 제공하는 새로운 기능을 살펴보면
또한 현재 상태를 객체에 바인딩 할 수 있습니다.

#include <string>
#include <iostream>
#include <functional>


std::function<void(std::string const&)> getLambda(std::string const& first)
{
    // Here we bind `first` to the function
    // The second parameter will be passed when we call the function
    return [first](std::string const& second) -> void
    {   std::cout << first << " " << second << "\n";
    };
}

int main(int argc, char* argv[])
{
    auto hw = getLambda("Hello");
    auto gw = getLambda("GoodBye");

    hw("World");
    gw("World");
}

2

간단한 함수를 생각해 보자.

function f1(x) {
    // ... something
}

이 함수는 다른 함수 내에 중첩되어 있지 않으므로 최상위 함수라고합니다. 모든 JavaScript 함수는 "Scope Chain" 이라는 객체 목록을 자체와 연관시킵니다 . 이 범위 체인은 정렬 된 객체 목록입니다. 이러한 각 객체는 일부 변수를 정의합니다.

최상위 기능에서 스코프 체인은 단일 객체 인 전역 객체로 구성됩니다. 예를 들어, f1위 함수 에는 모든 전역 변수를 정의하는 단일 객체가 포함 된 범위 체인이 있습니다. (여기서 "object"라는 용어는 JavaScript 객체를 의미하는 것이 아니라 JavaScript가 변수를 "찾을"수있는 변수 컨테이너 역할을하는 구현 정의 객체 일뿐입니다.)

이 함수가 호출되면 JavaScript는 "Activation object" 라는 것을 생성하고이를 스코프 체인의 맨 위에 놓습니다. 이 객체는 모든 로컬 변수를 포함합니다 (예 : x여기). 이제 스코프 체인에 두 개의 객체가 있습니다. 첫 번째 객체는 활성화 객체이고 그 아래는 전역 객체입니다.

두 개체는 서로 다른 시간에 스코프 체인에 배치됩니다. 전역 객체는 함수가 정의 될 때 (즉, JavaScript가 함수를 구문 분석하고 함수 객체를 생성 할 때) 놓이고, 활성화 객체는 함수가 호출 될 때 들어갑니다.

이제 우리는 이것을 알고 있습니다 :

  • 모든 기능에는 관련 범위 체인이 있습니다
  • 함수가 정의되면 (함수 객체가 생성 될 때) JavaScript는 해당 함수와 함께 범위 체인을 저장합니다
  • 최상위 레벨 함수의 경우, 스코프 체인은 함수 정의시 글로벌 오브젝트 만 포함하고 호출시 맨 위에 추가 활성화 오브젝트를 추가합니다.

중첩 함수를 처리 할 때 상황이 흥미로워집니다. 자, 하나를 만들어 봅시다 :

function f1(x) {

    function f2(y) {
        // ... something
    }

}

f1정의 되면 전역 객체 만 포함하는 범위 체인을 얻습니다.

이제 f1호출되면 범위 체인이 f1활성화 객체 를 가져옵니다. 이 활성화 객체는 변수 xf2함수 인 변수 를 포함합니다 . 그리고 그것은 f2정의되고 있습니다. 따라서 현재 JavaScript는에 대한 새로운 범위 체인을 저장합니다 f2. 이 내부 기능에 대해 저장된 범위 체인은 현재 범위 체인입니다. 현재 스코프 체인은입니다 f1. 그러므로 f2의 범위 체인은 f1S ' 현재 의 활성 객체 포함 - 범위 체인 f1글로벌 개체.

f2이 호출 되면을 포함하는 자체 활성화 객체를 y가져와 이미 범위의 활성화 객체 f1와 전역 객체를 포함하는 범위 체인에 추가됩니다 .

내에 정의 된 다른 중첩 함수가있는 f2경우 해당 범위 체인에는 정의시 3 개의 객체 (두 외부 함수의 활성화 객체 2 개와 전역 객체)가 있고 호출 시간에는 4 개가 포함됩니다.

이제 스코프 체인의 작동 방식을 이해했지만 클로저에 대해서는 아직 언급하지 않았습니다.

함수 객체와 함수 변수의 범위가 결정되는 범위 (변수 바인딩 세트)의 조합을 컴퓨터 과학 문헌의 폐쇄라고합니다. JavaScript는 David Flanagan의 최종 안내서입니다.

대부분의 함수는 함수가 정의되었을 때 유효한 것과 동일한 범위 체인을 사용하여 호출되며 클로저가 관련되어 있는지는 중요하지 않습니다. 클로저는 정의되었을 때 유효한 것과 다른 범위 체인에서 호출 될 때 흥미로워집니다. 중첩 함수 오브젝트가 정의 된 함수에서 리턴 될 때 가장 일반적으로 발생합니다 .

함수가 반환되면 해당 활성화 개체가 범위 체인에서 제거됩니다. 중첩 함수가 없으면 활성화 객체에 대한 참조가 더 이상 없으며 가비지 수집됩니다. 중첩 함수가 정의 된 경우 해당 함수 각각에 범위 체인에 대한 참조가 있으며 해당 범위 체인은 활성화 오브젝트를 나타냅니다.

그러나 중첩 된 함수 객체가 외부 함수 내에 남아 있으면 참조한 활성화 객체와 함께 가비지 수집됩니다. 그러나 함수가 중첩 함수를 정의하여 반환하거나 어딘가에 속성에 저장하면 중첩 함수에 대한 외부 참조가 있습니다. 가비지 수집되지 않으며 참조하는 활성화 객체도 가비지 수집되지 않습니다.

위의 예에서는 f2에서 반환하지 않으므로 반환 f1호출시 f1활성화 객체가 범위 체인에서 제거되고 가비지 수집됩니다. 그러나 우리가 이와 같은 것을 가지고 있다면 :

function f1(x) {

    function f2(y) {
        // ... something
    }

    return f2;
}

여기에 반환 f2은의 활성화 객체를 포함하는 범위 체인을 f1가지므로 가비지 수집되지 않습니다. 이 시점에서을 호출하면을 벗어난 경우에도 변수 f2에 액세스 할 수 있습니다 .f1xf1

따라서 우리는 함수가 스코프 체인을 유지하고 스코프 체인이 외부 함수의 모든 활성화 객체를 유지한다는 것을 알 수 있습니다. 이것이 폐쇄의 본질입니다. JavaScript의 함수는 "어휘 범위" 이며, 호출 될 때 활성화 된 범위와 반대로 정의되었을 때 활성화 된 범위를 저장합니다.

개인 변수 근사, 이벤트 기반 프로그래밍, 부분 응용 프로그램 등과 같은 클로저를 포함하는 많은 강력한 프로그래밍 기술이 있습니다 .

또한이 모든 것이 클로저를 지원하는 모든 언어에 적용됩니다. 예를 들어 PHP (5.3+), Python, Ruby 등


-1

클로저는 컴파일러 최적화 (일명 구문 설탕?)입니다. 일부 사람들은 이것을 가난한 사람의 대상 이라고도합니다 .

Eric Lippert의 답변보기 : (아래 발췌)

컴파일러는 다음과 같은 코드를 생성합니다.

private class Locals
{
  public int count;
  public void Anonymous()
  {
    this.count++;
  }
}

public Action Counter()
{
  Locals locals = new Locals();
  locals.count = 0;
  Action counter = new Action(locals.Anonymous);
  return counter;
}

말이 되나요?
또한 비교를 요청했습니다. VB와 JScript는 모두 거의 같은 방식으로 클로저를 만듭니다.


이 답변은 CW의 답변입니다. 왜냐하면 Eric의 훌륭한 답변에 대한 점수가 없습니다. 당신이 적합하다고 생각되면 그것을 upvote하십시오. HTH
goodguys_activate

3
-1 : 귀하의 설명이 C #에서 너무 근본입니다. 클로저는 여러 언어로 사용되며 이러한 언어에서 구문 설탕보다 훨씬 많으며 기능과 상태를 모두 포함합니다.
Martin York

1
아닙니다. 클로저는 단지 "컴파일러 최적화"나 구문 설탕이 아닙니다. -1
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.