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”的整数参数(与静态实例成员counter的名称相同)
从控制台测试应用程序Main()方法调用SelfCallingMethod

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

        Console.Read();
    }


现在的问题是,当循环进入无限循环时,因为当计数器方法级别变量的值达到value = 3时,线程控制就会退出该方法,并在方法级别计数器变量设置为2的情况下再次执行循环-我不确定为什么将此计数器设置为2。

一旦将方法参数名称计数器更改为静态实例字段名称以外的其他名称,就可以预期结果并且控制台将打印0、1、2

你能给我一个解释吗? .NET CLR中是否存在从TLS(线程本地存储)读取值的错误?

对于问题SelfCallingMethod的启动调用栈,我得到了问题所在,而循环条件始终评估2 == 2,这导致了无限循环。

最佳答案

您的代码永远不会使用静态字段。看一下这个循环:

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


counter是局部变量(参数)。然后将其按值传递给SelfCallingMethod,因此该方法调用不会更改它。除了通过异常,您如何期望退出循环?

因此,将发生的情况是您将获得一个带有SelfCallingMethod(0)的堆栈,该堆栈调用SelfCallingMethod(1)(在增量之后),该堆栈调用SelfCallingMethod(2),该调用又调用SelfCallingMethod(3)。这将增加其计数器的副本(至4)并返回...,但随后SelfCallingMethod(2)的循环将循环并再次调用SelfCallingMethod(3)。不要忘记,每次SelfCallingMethod调用都有一个单独的counter变量。


  一旦将方法参数名称计数器更改为静态实例字段名称以外的其他名称,就可以预期结果并且控制台将打印0、1、2


是的,因为那时所有在方法中使用counter的代码都使用该字段而不是局部变量。名称相同时,局部变量将隐藏静态变量。 (尽管您仍然可以使用SelfCallingTest.counter显式访问它。)


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


绝对不。恐怕是您代码中唯一的错误。

关于c# - 在类中声明相同名称实例级别的静态字段时,为什么会弄乱方法范围参数值,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9791930/

10-09 19:36