Почему значение параметра области действия метода искажается, когда в классе объявлено одно и то же статическое поле уровня экземпляра имени - PullRequest
2 голосов
/ 20 марта 2012
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» (то же имя, что и у статического элемента-счетчика экземпляра) SelfCallingMethod вызывается из консольного тестового метода Main ()

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

        Console.Read();
    }

Теперь проблема в том, что пока цикл находится в бесконечном цикле, потому что, когда значение переменной уровня метода счетчика достигает значения = 3, управление потоком выходит из метода и снова возобновляется при выполнении цикла с получением переменной счетчика уровня метода. установить на 2 - я не уверен, почему этот счетчик установлен на 2.

Как только я меняю счетчик имени параметра метода на другое, нежели статическое имя поля экземпляра, результаты ожидаются, и консоль печатает 0, 1, 2

Не могли бы вы дать мне объяснение? Есть ли ошибка в .NET CLR для чтения значения из TLS (локальное хранилище потока?)

Я понял, в чем здесь проблема, для инициирующего стека вызовов для метода SelfCallingMethod, в то время как условие цикла всегда оценивается как 2 == 2, и это вызывает бесконечный цикл.

Ответы [ 2 ]

7 голосов
/ 20 марта 2012

Ваш код никогда не использует статическое поле .Посмотрите на этот цикл:

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 (локальное хранилище потока?)

Абсолютно нет.Боюсь, единственная ошибка в вашем коде.

1 голос
/ 20 марта 2012

Счетчик параметров наиболее близок по объему - фактически на статическую переменную никогда не ссылаются из вашего кода.Ничто не увеличивает счетчик, на котором вы тестируете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...