是否有任何理由将参数值分配给方法内的局部变量以便使用这些值而不更改它们? IE。像下面这样:
private void MyMethod(string path)
{
string myPath = path;
StreamReader mystream = new StreamReader(myPath);
...
}
或者我总是可以这样说吗(上面的代码是多余的而且不干净):
private void MyMethod(string path)
{
StreamReader mystream = new StreamReader(path);
...
}
我知道它是双向的,但我想确保我的理解没有遗漏任何内容。
最佳答案
您唯一需要执行此操作(在本地分配)的情况是您在 foreach 循环中或使用 Linq。否则,您可能会遇到修改闭包的问题。
这是 MSDN 博客的一个片段(以下所有内容均来自链接)。
但我已经超前了。这个片段的输出是什么?
var values = new List<int>() { 100, 110, 120 };
var funcs = new List<Func<int>>();
foreach(var v in values)
funcs.Add( ()=>v );
foreach(var f in funcs)
Console.WriteLine(f());
大多数人期望它是 100/110/120。实际上是 120/120/120。为什么?
因为 ()=>v 的意思是“返回变量 v 的当前值”,而不是“返回创建委托(delegate)时 v 返回的值”。闭包关闭变量,而不是值。当这些方法运行时,显然最后分配给 v 的值是 120,所以它仍然是那个值。
这很令人困惑。正确的代码写法是:
foreach(var v in values)
{
var v2 = v;
funcs.Add( ()=>v2 );
}
现在发生了什么?每次我们重新启动循环体时,我们逻辑上都会创建一个全新的变量 v2。每个闭包都在不同的 v2 上关闭,v2 只分配一次,因此它始终保持正确的值。
基本上,问题的出现是因为我们指定 foreach 循环是 for 的语法糖
{
IEnumerator<int> e = ((IEnumerable<int>)values).GetEnumerator();
try
{
int m; // OUTSIDE THE ACTUAL LOOP
while(e.MoveNext())
{
m = (int)(int)e.Current;
funcs.Add(()=>m);
}
}
finally
{
if (e != null) ((IDisposable)e).Dispose();
}
}
如果我们指定扩展是
try
{
while(e.MoveNext())
{
int m; // INSIDE
m = (int)(int)e.Current;
funcs.Add(()=>m);
}
然后代码将按预期运行。
关于c# - 我应该先将参数值分配给局部变量而不是直接使用它们吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10267858/