Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/335.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么在构造函数参数超出范围后可以访问它?_C#_.net_Clr - Fatal编程技术网

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

C# 为什么在构造函数参数超出范围后可以访问它?,c#,.net,clr,C#,.net,Clr,为什么在下面的示例中可以调用SomeMethod()方法 我认为当Logger属性尝试访问构造函数参数loggerFactory时,它将不再可用 我在设置lazyLogger字段时使用了一个函数,但我认为在调用Logger属性时会抛出一个排序异常 但一切都很好。 这可能只是我对CLR/C工作原理的误解 我希望你能解释一下为什么会这样 public class TestClass { private readonly Lazy<ILogger> lazyLogger; pri

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

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

我在设置lazyLogger字段时使用了一个函数,但我认为在调用Logger属性时会抛出一个排序异常

但一切都很好。 这可能只是我对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);
  }
}
公共类TestClass
{
私人只读懒散记录器;
私有ILogger=>this.lazyLogger.Value;
公共测试类(ILoggerFactory loggerFactory)
{
this.lazyLogger=newlazy(()=>loggerFactory.GetLogger(“TestLogger”);
}
公共方法()
{
this.Logger.Info(“测试日志消息”);//为什么可以调用此方法?构造函数参数应该不再可用,对吗?
} 
}
公共接口工厂
{
ILogger GetLogger(字符串名称);
}
公共接口ILogger
{
无效信息(字符串消息);
}
公共类TestLoggerFactory:ILoggerFactory
{
公共ILogger GetLogger(字符串名称)
{
返回新的测试记录器(名称);
}
}
公共类测试记录器:ILogger
{
公共无效信息(字符串消息)
{
控制台写入线(消息);
}
}

因为您正在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); 
    }
公共类TestClass
{
/*你的田地在这里*/
//由编译器创建
私有Ilogger,匿名字段;
私有ILogger匿名方法()
{
返回anonymousField.GetLogger(“TestLogger”);
}
公共测试类(ILoggerFactory loggerFactory)
{
//保存字段
this.anonymousField=loggerFactory;
//将实例方法改为捕获匿名字段
this.lazyLogger=新的Lazy(匿名方法);
}

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

在传递给
Lazy
构造函数的委托中,您正在关闭
loggerFactory
。嘿,如果我将贵重物品放在一个框中,请给该框t哦,有人,他是怎么得到我的贵重物品的?我从来没有给过他,我只给了他一个盒子!@Lee,当你说我要结束的时候,你这是什么意思?结束的方面对我来说是新的。可能是我不了解这一点的错。实际上,编译器为lambda创建了一个新的委托类,其中包含捕获变量的字段@IssaFram抱歉,我的英语有时缺少这种编译器魔法的正确措辞。虽然这对于正常的对话来说已经足够了,但我始终不明白为什么它被称为“闭包”/“捕获”的确切含义是什么etc..在这个上下文中。@OlivierJacot Descombes对此不确定,前一段时间我检查了反编译的IL,我想我记得它尽可能将值保留在同一个类中。不确定这是否是一个实现细节。请参阅:和,以获取更深入的信息:。由Jon Skeet编写。