C# 中的委托问题
在下面的程序中,DummyMethod 总是打印 5。但是如果我们使用注释代码,我们会得到不同的值(即 1、2、3、4)。有人可以解释为什么会发生这种情况吗?
delegate int Methodx(object obj);
static int DummyMethod(int i)
{
Console.WriteLine("In DummyMethod method i = " + i);
return i + 10;
}
static void Main(string[] args)
{
List<Methodx> methods = new List<Methodx>();
for (int i = 0; i < 5; ++i)
{
methods.Add(delegate(object obj) { return DummyMethod(i); });
}
//methods.Add(delegate(object obj) { return DummyMethod(1); });
//methods.Add(delegate(object obj) { return DummyMethod(2); });
//methods.Add(delegate(object obj) { return DummyMethod(3); });
//methods.Add(delegate(object obj) { return DummyMethod(4); });
foreach (var method in methods)
{
int c = method(null);
Console.WriteLine("In main method c = " + c);
}
}
另外,如果使用以下代码,我会得到所需的结果。
for (int i = 0; i < 5; ++i)
{
int j = i;
methods.Add(delegate(object obj) { return DummyMethod(j); });
}
In the following program, DummyMethod always print 5. But if we use the commented code instead, we get different values (i.e. 1, 2, 3, 4). Can anybody please explain why this is happenning?
delegate int Methodx(object obj);
static int DummyMethod(int i)
{
Console.WriteLine("In DummyMethod method i = " + i);
return i + 10;
}
static void Main(string[] args)
{
List<Methodx> methods = new List<Methodx>();
for (int i = 0; i < 5; ++i)
{
methods.Add(delegate(object obj) { return DummyMethod(i); });
}
//methods.Add(delegate(object obj) { return DummyMethod(1); });
//methods.Add(delegate(object obj) { return DummyMethod(2); });
//methods.Add(delegate(object obj) { return DummyMethod(3); });
//methods.Add(delegate(object obj) { return DummyMethod(4); });
foreach (var method in methods)
{
int c = method(null);
Console.WriteLine("In main method c = " + c);
}
}
Also if the following code is used, I get the desired result.
for (int i = 0; i < 5; ++i)
{
int j = i;
methods.Add(delegate(object obj) { return DummyMethod(j); });
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
问题是您在每个委托中捕获相同的变量
i
- 在循环结束时该变量的值仅为 5。相反,您希望每个委托捕获不同的变量,这意味着在循环中声明一个新变量:
这是一个非常常见的“陷阱” - 您可以在 我的闭包文章。
The problem is that you're capturing the same variable
i
in every delegate - which by the end of the loop just has the value 5.Instead, you want each delegate to capture a different variable, which means declaring a new variable in the loop:
This is a pretty common "gotcha" - you can read a bit more about captured variables and closures in my closures article.
本文可能会帮助您了解正在发生的情况(即闭包是什么):http://blogs.msdn.com/oldnewthing/archive/2006/08/02/686456.aspx
This article will probably help you understand what is happening (i.e. what a closure is): http://blogs.msdn.com/oldnewthing/archive/2006/08/02/686456.aspx
如果您查看生成的代码(使用 Reflector),您可以看到差异:
当您使用初始代码时,它会在后台创建一个临时类,该类保存对“i”变量的引用,因此根据 Jon 的回答,你只能看到它的最终值。
我真的建议查看 Reflector 中的代码,看看发生了什么,这就是我的方式理解捕获的变量。确保在选项菜单中将代码优化设置为“.NET 1.0”,否则它将隐藏所有幕后内容。
If you look at the code generated (using Reflector) you can see the difference:
When you use the initial code it creates a temporary class in the background, this class holds a reference to the "i" variable, so as per Jon's answer, you only see the final value of this.
I really recommend looking at the code in Reflector to see what's going on, its how I made sense of captured variables. Make sure you set the Optimization of the code to ".NET 1.0" in the Option menu, otherwise it'll hide all the behind scenes stuff.
我认为这是因为变量
i
被放入堆中(它是一个捕获的变量)看看这个答案。
I think it is because the variable
i
is put to the heap (it's a captured variable)Take a look at this answer.