2017-12-20 1 views
-1

아래 예제에서 SomeMethod() 메서드를 호출하는 것이 좋은 이유는 무엇입니까?범위를 벗어난 생성자 매개 변수에 액세스 할 수있는 이유는 무엇입니까?

은 내가 로거 속성에 액세스하려고 할 때 생성자 매개 변수 loggerFactory 더 이상 사용할 수없는 것이라고 생각합니다. 나는이 기능을 사용하고

나는 lazyLogger 필드를 설정,하지만 난이 로거 속성을 호출 할 때이 종류의 예외를 던질 것이라고 생각합니다.

하지만 모든 것이 잘 작동합니다. 이것은 CLR/C#이 어떻게 작동하는지에 대한 오해 일 수 있습니다.

왜 이렇게 작동하는지 설명해 주시면 감사하겠습니다. 당신이 람다

() = > loggerFactory.GetLogger("TestLogger"); 

컴파일러 내부에이 매개 변수를 액세스하는 때문에

public class TestClass 
{ 
    private readonly Lazy<ILogger> lazyLogger; 

    private ILogger Logger => this.lazyLogger.Value; 

    public TestClass(ILoggerFactory loggerFactory) 
    { 
    this.lazyLogger = new Lazy<ILogger>(() = > loggerFactory.GetLogger("TestLogger")); 
    } 

    public void SomeMethod() 
    { 
    this.Logger.Info("Test Log Message"); //Why is it okay to call this method? The constructor parameter shouldn't be available anymore, right? 
    } 
} 

public interface ILoggerFactory 
{ 
    ILogger GetLogger(string name); 
} 

public interface ILogger 
{ 
    void Info(string message); 
} 

public class TestLoggerFactory : ILoggerFactory 
{ 
    public ILogger GetLogger(string name) 
    { 
     return new TestLogger(name); 
    } 
} 

public class TestLogger : ILogger 
{ 
    public void Info(string message) 
    { 
    Console.WriteLine(message); 
    } 
} 
+3

'Lazy '생성자에 전달 된 델리게이트에서'loggerFactory'를 닫습니다. – Lee

+2

안녕하세요, 귀중품을 상자에 넣은 다음 그 상자를 다른 사람에게 주면 어떻게 그 귀중품을 가져 왔습니까? 나는 그 (것)들을 결코주지 않았다, 나는 그에게 단지 상자를 주었다! –

+0

@Lee, 내가 ** 클로저한다고 말하면 ** 그게 무슨 뜻이야? –

답변

2

는 그 변수를 캡처 할 몇 가지 추가 코드를 생성합니다.

public class TestClass 
{ 
    /* your fields here */ 

    // created by compiler 
    private ILoggerFactory anonymousField; 
    private ILogger AnonymousMethod() 
    { 
     return anonymousField.GetLogger("TestLogger"); 
    } 

    public TestClass(ILoggerFactory loggerFactory) 
    { 
     // save field 
     this.anonymousField = loggerFactory; 
     // use instance method instead with captures anonymousField 
     this.lazyLogger = new Lazy<ILogger>(AnonymousMethod); 
    } 

주석에서 언급했듯이 사실 익명 메소드를 선언하고 필요한 모든 변수를 필드로 사용하는 완전히 새로운 클래스가 생성됩니다. 하지만 이것이 기본 아이디어입니다.

+0

** closing ** 애스펙트는 새로운 것입니다. 이 지식이 없으면 내 잘못 일 수 있습니다. –

+1

사실 컴파일러는 캡쳐 된 변수의 필드를 포함하는 람다에 대한 새로운 델리게이트 클래스를 만듭니다. –

+1

@IssaFram 죄송합니다, 제 영어에는 때때로이 컴파일러 마술에 맞는 정확한 문구가 없습니다. 정상적인 대화를하기에 충분하지만, 왜 그것이 "클로저"/ "캡쳐"등의 정확한 의미인지는 알 수 없습니다. –

관련 문제