2017-12-20 10 views
-1

私の例でSomeMethod()メソッドを呼び出すのはなぜですか?コンストラクタパラメータが有効範囲外になった後、コンストラクタパラメータにアクセスできるのはなぜですか?

は私がロガープロパティがアクセスしようとしたとき、コンストラクタのパラメータloggerFactoryが使用できなくと思うだろう。

私はlazyLoggerフィールドを設定したとき、私は、関数を使用していますが、私はロガープロパティを呼び出すとき、それは一種の例外をスローするだろうと思いました。

しかし、すべてうまく動作します。 これは、CLR/C#がどのように機能するかについての私の誤解かもしれません。

なぜこのように動作するのか説明していただきたいと思います。

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

あなたは

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

ラムダの内部では、このパラメータにアクセスしているので、コンパイラはその変数をキャプチャするためにいくつかの余分なコードを作成します。

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

**閉じる以上の側面は私には新しいものです。この知識がないのは私のせいかもしれない。 –

+1

実際には、コンパイラはキャプチャされた変数のフィールドを含むラムダ用の新しいデリゲートクラスを作成します。 –

+1

@IssaFram申し訳ありませんが、私の英語では、このコンパイラの魔法の正しい言葉が欠けていることがあります。通常の会話では十分ですが、なぜそれが呼び出されたのか、「閉鎖」/「キャプチャ」などの正確な意味がこの文脈では理解できません。 –

関連する問題