Cannot refer to a non-final variable i inside an inner class defined in a differ

涉及到闭包(closure)的概念。

 

不同语言对闭包选择了不同的支持,相比之下,C#中就能够在匿名函数中引用非final的外部变量,例如这篇帖子中提到的C#代码:

List<Func<int>> actions = new List<Func<int>>();

int variable = 0;
while (variable < 5)
{
    actions.Add(() => variable * 2);
    ++ variable;
}

foreach (var act in actions)
{
    Console.WriteLine(act.Invoke());
}

这一行:

actions.Add(() => variable * 2);

就在匿名方法内引用了外部局部变量: variable.

 

但同时也引起了一个奇怪的问题,上面的C#代码,我们期望的结果应该是输出"0, 2, 4, 6, 8"才对,结果却是10个零。

 

原因就是C# compiler 在所闭的包内圈入了对variable的引用,然后当运行

Console.WriteLine(act.Invoke());

时,variable值已经变成5,结果输出为10个零。

 

这种特性多少有点令人意外,可能java正是为了避免这种情形,于是强制规定闭包内引用的外部局部变量必须为final,想象一下如果上例中variable 为final的话,自然就不会写出上面的代码,造成类似的意外了。

 

另外,上例中如果你希望达到输出"0, 2, 4, 6, 8"的效果,可以:

while (variable < 5)
{
    int copy = variable;
    actions.Add(() => copy * 2);
    ++ variable;
}

 

 

ps.参考了很多文章,理解也仍然算不上透彻,列举在下,供包括自己的后来人参考

 

  http://stackoverflow.com/questions/5997953/cannot-refer-to-a-non-final-variable-i-inside-an-inner-class-defined-in-a-differe

  http://stackoverflow.com/questions/1299837/cannot-refer-to-a-non-final-variable-inside-an-inner-class-defined-in-a-different

  http://stackoverflow.com/questions/271440/c-captured-variable-in-loop

  http://blogs.msdn.com/b/ericlippert/archive/2003/09/17/what-are-closures.aspx

  http://csharpindepth.com/Articles/Chapter5/Closures.aspx

  http://en.wikipedia.org/wiki/Closure_(computer_science)

  http://zh.wikipedia.org/wiki/%E9%97%AD%E5%8C%85_(%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%A7%91%E5%AD%A6)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值