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

use*_*530 2 .net c# 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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

        Console.Read();
    }
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

Jon*_*eet 7

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

while (counter <= 2)
{
    SelfCallingMethod(counter);
}
Run Code Online (Sandbox Code Playgroud)

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读取值的错误(线程本地存储?)

绝对不.我担心你的代码中唯一的错误.