2009-07-16 4 views
4

Lambda (델리게이트로 사용되는 경우)가 호출 될 때마다 새 인스턴스를 만들지, 또는 컴파일러가 델리게이트를 한 번만 인스턴스화하고 해당 인스턴스를 전달할 수 있는지 여부에 대해 궁금합니다.lambda는 호출 될 때마다 새 인스턴스를 생성합니까?

더 구체적으로 말하면 사용자 지정 콜백을 전달하기 위해 람다 (lambda)를 사용할 수있는 XNA 게임용 API를 만들고 싶습니다. 이 메서드는 초당 여러 번 호출되는 Update 메서드에서 호출되므로 대리자를 전달할 때마다 매번 인스턴스를 새로 작성하면 상당히 나 빠질 수 있습니다. 때 수

InputManager.GamePads.ButtonPressed(Buttons.A, s => s.MoveToScreen<NextScreen>()); 
+5

참고로, ildasm 또는 다른 디 컴파일 도구를 사용하여 생성 된 코드를 볼 수 있습니다. 그렇게하면 위임은 한 번 생성되어 정적 필드에 캐시 된 다음이 코드 경로에 도달 할 때마다 다시 사용된다는 것을 알 수 있습니다. lambda가 "this"참조 또는 외부 변수를 사용하면 대리자는 해당 closure에 종속되므로 새 closure 환경이 필요할 때마다 다시 만들어야합니다. –

답변

2

예, 그것은을 캐시합니다 :

using System; 

class Program { 
    static void Main(string[] args) { 
     var i1 = test(10); 
     var i2 = test(20); 
     System.Console.WriteLine(object.ReferenceEquals(i1, i2)); 
    } 

    static Func<int, int> test(int x) { 
     Func<int, int> inc = y => y + 1; 
     Console.WriteLine(inc(x)); 
     return inc; 
    } 
} 

그것은 정적 필드를 만들고, 그것이 null의 경우, 새로운 대리인으로 채 웁니다, 그렇지 않으면 기존의 대리자를 반환합니다.

출력 10, 20, 참.

3

나는 이런 종류의 것이 항상 새로운 객체를 생성 할 것이므로 자주 호출되는 코드에서는 피해야한다고 생각했기 때문에 나는 당신의 질문에 흥미를 느꼈다.

내가 ildasm을 사용하여 장면 뒤에서 정확히 무엇이 일어나는지 알아낼 수있을 것이라고 생각합니다. 제 경우에는 델리게이트가 호출 될 때마다 새로운 객체가 생성된다는 것이 밝혀졌습니다. 코드가 매우 복잡하고 상황을 이해하기가 쉽지 않기 때문에 코드를 게시하지 않겠습니다. 이것은 MichaelGG가 제공 한 답변과 충돌합니다. 왜냐하면 그의 예에서는 정적 함수를 사용하기 때문입니다. 한 가지 방법으로 모든 것을 고안하고 나중에 문제가 있음을 알아 내기 전에 직접 시도해 보시기 바랍니다. ildasm은 (http://msdn.microsoft.com/en-us/library/f7dy01k1.aspx) 가야 할 길입니다. "newobj"라인을 찾으십시오. 원하지 않습니다.

또한 CLR 프로필을 사용하여 람다 함수가 메모리를 할당하고 있는지 알아볼 가치가 있습니다 (http://www.microsoft.com/downloads/details.aspx?familyid=A362781C-3870-43BE-8926-862B40AA0CD0&displaylang=en). 프레임 워크 2.0 용이지만 3.5 용으로도 작동하며 최신 버전이 제공됩니다.

관련 문제