[.net] .NET에서 ‘클로저’란 무엇입니까?

폐쇄 란 무엇입니까 ? .NET에 있습니까?

그들이 .NET에 존재한다면 그것을 설명하는 코드 스 니펫 (바람직하게는 C #)을 제공 할 수 있습니까?



답변

이 주제에 관한 기사 가 있습니다 . (예제가 많습니다.)

본질적으로 클로저는 나중에 실행될 수있는 코드 블록이지만 처음 작성된 환경을 유지합니다. 즉, 그 이후에도이를 생성 한 메소드의 로컬 변수 등을 계속 사용할 수 있습니다. 메소드 실행이 완료되었습니다.

클로저의 일반적인 기능은 C #에서 익명 메소드와 람다 식으로 구현됩니다.

다음은 익명 메소드를 사용하는 예입니다.

using System;

class Test
{
    static void Main()
    {
        Action action = CreateAction();
        action();
        action();
    }

    static Action CreateAction()
    {
        int counter = 0;
        return delegate
        {
            // Yes, it could be done in one statement; 
            // but it is clearer like this.
            counter++;
            Console.WriteLine("counter={0}", counter);
        };
    }
}

산출:

counter=1
counter=2

여기서 CreateAction에 의해 반환 된 액션은 여전히 ​​카운터 변수에 액세스 할 수 있으며 CreateAction 자체가 완료된 경우에도 실제로 증가시킬 수 있습니다.


답변

C #에서 Closure를 구현하는 방법에 관심이있는 경우 “답변을 알고 있습니다 (42) 블로그”

컴파일러는 백그라운드에서 클래스를 생성하여 성가신 메소드와 변수 j를 캡슐화합니다.

[CompilerGenerated]
private sealed class <>c__DisplayClass2
{
    public <>c__DisplayClass2();
    public void <fillFunc>b__0()
    {
       Console.Write("{0} ", this.j);
    }
    public int j;
}

기능 :

static void fillFunc(int count) {
    for (int i = 0; i < count; i++)
    {
        int j = i;
        funcArr[i] = delegate()
                     {
                         Console.Write("{0} ", j);
                     };
    }
}

그것을 다음으로 전환 :

private static void fillFunc(int count)
{
    for (int i = 0; i < count; i++)
    {
        Program.<>c__DisplayClass1 class1 = new Program.<>c__DisplayClass1();
        class1.j = i;
        Program.funcArr[i] = new Func(class1.<fillFunc>b__0);
    }
}


답변

클로저는 원래 범위에서 변수 값을 유지하는 기능 값입니다. C #은 익명 대리자 형태로 사용할 수 있습니다.

매우 간단한 예를 보려면 다음 C # 코드를 사용하십시오.

    delegate int testDel();

    static void Main(string[] args)
    {
        int foo = 4;
        testDel myClosure = delegate()
        {
            return foo;
        };
        int bar = myClosure();

    }

마지막에 bar가 4로 설정되고 myClosure 델리게이트를 전달하여 프로그램의 다른 곳에서 사용할 수 있습니다.

클로저는 지연된 실행 또는 인터페이스 단순화와 같은 많은 유용한 것들에 사용될 수 있습니다. LINQ는 주로 클로저를 사용하여 구축됩니다. 대부분의 개발자에게 가장 편리한 방법은 동적으로 생성 된 컨트롤에 이벤트 처리기를 추가하는 것입니다. 다른 곳에 데이터를 저장하지 않고 컨트롤을 인스턴스화 할 때 클로저를 사용하여 동작을 추가 할 수 있습니다.


답변

Func<int, int> GetMultiplier(int a)
{
     return delegate(int b) { return a * b; } ;
}
//...
var fn2 = GetMultiplier(2);
var fn3 = GetMultiplier(3);
Console.WriteLine(fn2(2));  //outputs 4
Console.WriteLine(fn2(3));  //outputs 6
Console.WriteLine(fn3(2));  //outputs 6
Console.WriteLine(fn3(3));  //outputs 9

클로저는 생성 된 함수 외부로 전달되는 익명 함수입니다. 사용하는 함수에서 변수를 유지 관리합니다.


답변

다음은 JavaScript에서 비슷한 코드로 만든 C #에 대한 좋은 예입니다.

public delegate T Iterator<T>() where T : class;

public Iterator<T> CreateIterator<T>(IList<T> x) where T : class
{
        var i = 0;
        return delegate { return (i < x.Count) ? x[i++] : null; };
}

위의 코드를 사용하는 방법을 보여주는 코드는 다음과 같습니다.

var iterator = CreateIterator(new string[3] { "Foo", "Bar", "Baz"});

// So, although CreateIterator() has been called and returned, the variable 
// "i" within CreateIterator() will live on because of a closure created 
// within that method, so that every time the anonymous delegate returned 
// from it is called (by calling iterator()) it's value will increment.

string currentString;
currentString = iterator(); // currentString is now "Foo"
currentString = iterator(); // currentString is now "Bar"
currentString = iterator(); // currentString is now "Baz"
currentString = iterator(); // currentString is now null

그것이 다소 도움이되기를 바랍니다.


답변

클로저는 이벤트 나 델리게이트가 정의 될 때와 같이 나중에 호출되거나 실행될 수있는 외부의 변수 (스택에서 변수 아래)를 참조하는 코드 덩어리입니다. ) … 코드 청크가 참조하는 외부 변수가 범위를 벗어날 수 있고 그렇지 않으면 손실되었을 수 있으므로 코드 청크에 의해 참조된다는 사실 (클로저라고 함)은 런타임에 “hold” “코드의 청크 청크에 의해 더 이상 필요하지 않을 때까지 범위 내의 변수 …


답변

기본적으로 클로저는 함수에 인수로 전달할 수있는 코드 블록입니다. C #은 익명 대리자 형식의 폐쇄를 지원합니다.

간단한 예제는 다음과 같습니다.
List.Find 메서드는 목록 항목을 찾기 위해 코드 조각 (클로저)을 수락하고 실행할 수 있습니다.

// Passing a block of code as a function argument
List<int> ints = new List<int> {1, 2, 3};
ints.Find(delegate(int value) { return value == 1; });

C # 3.0 구문을 사용하여 다음과 같이 작성할 수 있습니다.

ints.Find(value => value == 1);