当在类中声明相同名称实例级静态字段时,为什么方法范围参数值被搞乱

时间:2012-03-20 17:29:26

标签: c# .net clr

public class SelfCallingTest
{
    private static int counter;

    public void SelfCallingMethod(int counter)
    {
        Console.WriteLine("The input integer is: {0} ", counter);

        counter++;

        while (counter <= 2)
        {
            SelfCallingMethod(counter);
        }
    }
}

上面的SelfCallingTest类有一个静态字段名“counter”,SelfCallingMethod接受一个名为“counter”的整数参数(与静态实例成员计数器同名) 从控制台测试应用程序Main()方法

调用SelfCallingMethod
static void Main(string[] args)
    {           
        SelfCallingTest sct = new SelfCallingTest();
        sct.SelfCallingMethod(0);

        Console.Read();
    }

现在问题是while循环进入无限循环,因为当计数器方法级别变量的值达到value = 3时,线程控制从方法中出来并再次恢复,而循环执行时方法级别计数器变量获取设置为2 - 我不确定为什么这个计数器设置为2。

只要将方法参数名称计数器更改为非静态实例字段名称,结果就会出现,控制台正在打印0,1,2

你能告诉我一个解释吗? .NET CLR中是否存在从TLS(线程本地存储?)

读取值的错误

我遇到了问题所在,对于方法SelfCallingMethod的初始调用堆栈,而循环条件总是在评估2 == 2,这就是导致无限循环。

2 个答案:

答案 0 :(得分:7)

您的代码从不使用静态字段。看看这个循环:

while (counter <= 2)
{
    SelfCallingMethod(counter);
}

counter本地变量(参数)。然后它由 value 传递给SelfCallingMethod,因此方法调用不会改变它。除了通过例外之外,您期望如何退出循环?

所以会发生什么事情,你会得到一个SelfCallingMethod(0)的堆栈,它会调用SelfCallingMethod(1)(在增量之后)调用调用SelfCallingMethod(2)的{​​{1}}。这将增加其计数器的副本(到4)并返回...但是来自SelfCallingMethod(3)的循环将转过来并再次调用SelfCallingMethod(2)。不要忘记,SelfCallingMethod(3)的每次通话都有一个单独的 SelfCallingMethod变量。

  

只要将方法参数名称计数器更改为非静态实例字段名称,结果就会出现,控制台正在打印0,1,2

是的,因为此时在方法中使用counter的所有代码都使用字段而不是局部变量。当名称相同时,局部变量隐藏静态变量。 (你仍然可以使用counter明确地访问它。)

  

.NET CLR中是否存在从TLS(线程本地存储?)读取值的错误

绝对不是。唯一的错误就在你的代码中,我很害怕。

答案 1 :(得分:1)

参数计数器的范围最接近 - 事实上,静态变量永远不会从您的代码中引用。你正在测试的计数器没有任何增加。