C # Для вывода типа Loop при использовании var - PullRequest
1 голос
/ 08 ноября 2011

Рассмотрим следующий код ...

            double total = Int32.MaxValue;
            total++;

            int previousX = 0;

            for (var x = 0; x <= total; x++)
            {
                if (x == Int32.MaxValue)
                {
                    Console.WriteLine("Int32 max reached.");
                }

                if (x < 0)
                {
                    Console.WriteLine("Counter now < 0.");
                }

                previousX = x;
            }

Может показаться, что если вы используете var с циклом for, вывод типа по умолчанию имеет тип int.

Это правильно?потому что если счетчик выходит за максимум для int 32, вместо переполнения стека он сбрасывает себя обратно в ноль, а затем ведет обратный отсчет от нуля.

Примечание: previousX позволяет вам установить контрольные точки и посмотреть, что в предыдущемзначение счетчика "x" было.

Кто-нибудь знает, почему это происходит?

Кажется возможным получить немного рассол, используя var для счетчика цикла for.

Ответы [ 8 ]

6 голосов
/ 08 ноября 2011

Тип x определяется начальным значением, которое выше является целочисленным литералом 0.

Если вы хотите, чтобы x было двойным, используйте двойной литерал 0D.

3 голосов
/ 08 ноября 2011

Важно понимать, что ключевое слово var не означает «вариант» и не указывает на то, что переменная свободно набрана или имеет позднюю привязку. Это просто означает, что компилятор определяет и назначает наиболее подходящий тип. Поскольку у вас есть var x=0, он определяет, что x является int, чтобы соответствовать 0. Так что да, это правильный функционал.

Из-за способа представления отрицательных чисел (комплименты двух) в виде числа, превышающего его максимальное значение, оно будет сброшено и будет отсчитываться от -1 и далее.

Увеличение на x++ не произойдет, пока эта итерация цикла не завершится.

2 голосов
/ 08 ноября 2011

Это действительно интересно, но не связано с использованием var. Это все еще происходит при использовании int (или на самом деле long, short и т. Д.).

Фактический виновник здесь в том, что значение MAX для цикла больше, чем максимальное значение для int32. при увеличении числового значения число будет переноситься, вызывая бесконечный цикл. Вы можете объявить var x, int x, short x и все из них зациклились бы аналогичным образом.

Характер увеличения числовых значений вызывает «обтекание». Вы можете попробовать это, запустив следующий код и наблюдая за значениями до и после увеличения. (Это также работает, если вы добавляете декремент).

        int a = Int32.MaxValue;
        Console.WriteLine(a);
        a++;
        Console.WriteLine(a);

        short b = Int16.MaxValue;
        Console.WriteLine(b);
        b++;
        Console.WriteLine(b);

        long c = Int64.MaxValue;
        Console.WriteLine(c);
        c++;
        Console.WriteLine(c);

Кроме того, переменная в размещенном фрагменте кода устанавливается в int с помощью оператора var x = 0. «0» само по себе является int и, следовательно, тип x устанавливается в int. Если вы укажете var x = 0F или 0L, тип будет другим.

2 голосов
/ 08 ноября 2011

Конечно, если вы увеличиваете int до MaxValue, оно возвращается к MinValue и начинает увеличиваться оттуда.

1 голос
/ 08 ноября 2011

var x = 0 собирается сделать вывод, что x является целым числом, потому что вы используете целочисленный литерал ("0").

Проверьте этот связанный пост о переполнении целого числа:

почему это приведет к длинному целочисленному переполнению

1 голос
/ 08 ноября 2011

Здесь ничего особенного не происходит. var будет выведено как Int32, потому что это то, что 0 по умолчанию. Если вы хотите долго использовать var x = 0L. Или просто long x = 0

1 голос
/ 08 ноября 2011

Var точный тип определяется вашим использованием оператора =. В c# 0 имеет тип int, поэтому компилятор использует int.

0 голосов
/ 08 ноября 2011

Это выглядит довольно просто:

var x = new User()

Когда компилятор видит эту строку, он заменяет var на User, потому что это то, что возвращает конструктор.То же самое происходит с вызовами функций:

var x = y.ToString()

ToString() возвращает string, поэтому компилятор знает, что заменить var на

Когда вы пишете

var x = 0

вы на самом деле вызываете int конструктор, поэтому var заменяется на int

У вас есть три варианта:

  • double x = 0 ...
  • var x = 0.0 ...
  • var x = 0D ...

Примечание: D суффикс для double

...