C# 在循环内捕获变量

匿名方法捕获变量:

static MethodInvoker CreateDelegateInstance(  ){
    int counter = 5;

    MethodInvoker ret = delegate{
        Console.WriteLine( counter );
        counter++;
    }

    ret();
    return ret;
}

MethodInvoker x = CreateDelegateInstance();
x();
x();

这里匿名方法捕获了变量 counter, 编译器会创建一个额外的类来容纳变量,CreateDelegateInstance 方法拥有对该类的一个实例引用,并且委托也有该实例的一个引用。

这个实例和其他实例一样也被保存在堆上,除非委托准备好呗垃圾回收,否则那个实例不会被回收的。

如果只捕捉this,就不需要额外的类型,编译器将直接创建一个实例方法来作为委托的操作。

 

对于一个捕获变量,只要还有任何委托实例在引用它,它就会一直存在。

 

局部变量所需的全部空间都在方法开始时的栈上分配。因此下面的代码不会产生每次循环迭代都“重新声明”变量的开销。

(如果是局部对象,也是栈上保存局部对象,然后局部对象指向一个堆上的空间)

int single;
for( int i=0; i<10; ++i ){
    single = 5;
    Console.WriteLine( single +i );
}

for (int i = 0; i < 10; ++i)
{
 	int multiple = 5;
    Console.WriteLine(multiple+i);
}

但是,一旦如果使用了变量捕获,那么循环内的变量将实例化多次,每次循环迭代时捕获的变量是不同的。

MethodInvoker[] delegates = new MethodInvoker[2];
for (int i = 0; i < 2; ++i)
{
   int multiple = 5;
            
   delegates[i] = delegate
   {
       multiple++;
       Console.WriteLine( "multiple: {0}", multiple );
   };
}
delegates[0]();//输出6
delegates[1]();//输出6

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值