2012-04-22 37 views
2

是否有任何理由将参数值分配给方法中的局部变量以便使用这些值而不更改它们?即像下面这样:我应该先将参数值分配给局部变量,而不是直接使用它们?

private void MyMethod(string path) 
{ 
    string myPath = path; 
    StreamReader mystream = new StreamReader(myPath); 
    ... 
} 

或者,我可以随时把它像这样(和上面的代码是多余的,只是不干净):

private void MyMethod(string path) 
{ 
    StreamReader mystream = new StreamReader(path); 
    ... 
} 

我知道这两种方式都可以,但我喜欢确定我的理解中没有遗漏任何东西。

+1

假设该变量没有在其他地方使用,我可以看到的第一种情况的唯一原因是帮助调试。 – ChrisF 2012-04-22 12:24:07

回答

3

这是完全一样的东西,唯一的区别是在第一种情况下,你创建了一个引用的副本(当方法超出范围时会被销毁,当执行结束时会发生这种情况)。

为了更好的可读性,坚持第二种情况。

+0

请注意,这并不总是最好的情况。在某些情况下,这可能会导致问题取决于如何使用变量。有关更多详情,请参阅下面的答案。 – tsells 2012-04-22 23:00:13

1

我更喜欢第二种选择。用参数创建一个新变量是没有意义的。另外,从阅读的角度来看,从路径(您收到的路径)创建流更有意义,而不是实例化“myPath”变量。

4

只有当你需要这样做(本地分配)时,如果你在foreach循环或使用Linq。否则,您可能遇到修改关闭的问题。

以下是来自MSDN博客的摘录(以下所有内容均来自链接)。

http://blogs.msdn.com/b/ericlippert/archive/2009/11/12/closing-over-the-loop-variable-considered-harmful.aspx

但我自己走在前面。这个片段的输出是什么?

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的当前值”,而不是“创建委托时返回值v返回”。闭包关闭变量,而不是超过值。当这些方法运行时,显然分配给v的最后一个值是120,所以它仍然有这个值。

这很混乱。编写代码的正确方法是:

foreach(var v in values) 
{ 
    var v2 = v; 
    funcs.Add(()=>v2); 
} 

现在会发生什么情况?每次我们重新启动循环体时,我们都会在逻辑上创建一个新的变量v2。每个闭包在一个不同的v2上关闭,该v2只分配一次,因此它始终保持正确的值。

基本上,问题就出现了,因为我们指定foreach循环是

{ 
    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); 
    } 

那么代码会像预期的那样。

相关问题