为什么在超出范围后可以访问构造函数参数?

时间:2017-12-20 17:07:13

标签: c# .net clr

为什么可以在下面的示例中调用 SomeMethod()方法?

我认为当 Logger 属性试图访问它时,构造函数参数 loggerFactory 将不再可用。

我在设置 lazyLogger 字段时使用了一个函数,但我认为当我调用 Logger 属性时会抛出异常。< / p>

但是一切都很好。 这可能只是我对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);
  }
}

1 个答案:

答案 0 :(得分:2)

因为您在lambda

中访问此参数
() = > 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); 
    }

正如评论中所提到的,实际上生成了一个全新的类,它声明了匿名方法并将所有必需的变量作为字段。但那是基本的想法。