Вопрос инициализации переменной C # - PullRequest
14 голосов
/ 04 июня 2009

Есть ли разница в том, инициализирую ли я целочисленную переменную, например:

int i = 0;
int i;

Компилятор или CLR рассматривают это как одно и то же? IIRC, я думаю, что они оба рассматриваются как одно и то же, но я не могу найти эту статью.

Ответы [ 8 ]

14 голосов
/ 04 июня 2009

Если переменная i является переменной экземпляра, ей будет автоматически присвоено значение 0. Если это локальная переменная в методе, она не определена, поэтому вам необходимо присвоить ей значение перед использованием.

Например:

class Program
{
    static void Main(string[] args)
    {
        intTest it;

        it = new intTest();

        Console.ReadLine();
    }

    class intTest
    {
        int i;

        public intTest()
        {
            int i2;

            Console.WriteLine("i = " + i);
            Console.WriteLine("i2 = " + i2);
        }
    }
}

Выше не скомпилируется, потому что i2 не назначен. Однако, присваивая 0 i2, т.е.

int i2 = 0;

и компиляция, а затем запуск, покажет, что оба теперь назначены 0.

7 голосов
/ 04 июня 2009

Я посмотрел на IL (используя ildasm) и это правда, что только int, установленный в 0, действительно установлен в 0 в конструкторе.

public class Class1
{
    int setToZero = 0;
    int notSet;
}

Формирует:

.method public hidebysig specialname rtspecialname 
        instance void  .ctor() cil managed
{
  // Code size       15 (0xf)
  .maxstack  8
  IL_0000:  ldarg.0
  IL_0001:  ldc.i4.0
  IL_0002:  stfld      int32 ClassLibrary1.Class1::setToZero
  IL_0007:  ldarg.0
  IL_0008:  call       instance void [mscorlib]System.Object::.ctor()
  IL_000d:  nop
  IL_000e:  ret
} // end of method Class1::.ctor
4 голосов
/ 04 июня 2009

Да, это одно и то же.

Вы можете обратиться к этой статье на Coding Horror

1 голос
/ 01 января 2013

Различные ответы здесь вводят в заблуждение, включая ссылочную статью на веб-сайте «Coding Horror».

Компилятор оптимизирует ваш код для удаления всех «ненужных» инициализаций, когда настроен на оптимизацию сгенерированного кода. Обратите внимание, что это поведение по умолчанию при компиляции в режиме «Release».

Я, например, думаю, что всегда очень полезно инициализировать все ваши переменные. Падение производительности в режиме отладки будет минимальным, а в режиме выпуска - ни одним, но выигрыш от явной установки переменных будет огромен для любого, кто будет поддерживать код в будущем, в лучшем стиле «документирование кода с кодом». Я помню своего очень опытного коллегу, который считал, что значение Int32 по умолчанию - Int32.MinValue вместо 0. Эти типы путаницы всегда случаются с вещами, вовлеченными в код, и, по моему мнению, их следует избегать в большинстве случаев.

1 голос
/ 05 июня 2009

После всего этого разговора стоит упомянуть ключевое слово "default" в C #.

т.е. int i; эквивалентно int i = default(int);, что эквивалентно int i = 0; и MyClass o = default(MyClass); эквивалентно MyClass o = null;

Это особенно актуально при использовании методов linq, таких как .SingleOrDefault(), потому что вы всегда можете использовать следующее, чтобы сделать ваш код более читабельным:

int someValue = collection.<various linq methods>.SingleOrDefault();
if (someValue == default(int))
{
  //Code for the default case
}

и

MyClass someValue = collection.<various linq methods>.SingleOrDefault();
if (someValue == default(MyClass))
{
  //Code for the default case
}
1 голос
/ 04 июня 2009

Как показывают следующие ссылки, они точно такие же:

http://msdn.microsoft.com/en-us/library/aa664742%28VS.71%29.aspx

0 голосов
/ 05 июня 2009

Они эквивалентны только для полей (переменных класса). Полям автоматически присваиваются значения по умолчанию при инициализации класса. Внутри метода или свойства неназначенная переменная остается неназначенной и вызовет ошибку компилятора, если вы попытаетесь получить доступ к ее значению.

0 голосов
/ 04 июня 2009

Каждый раз, когда вы создаете тип в C #, он автоматически заполняется дополненными нулями. В случае класса (ссылочного типа) это равняется нулевому указателю. Итак, технически, когда вы работаете с классами, следующее идентично:

MyClass class;
MyClass class2 = null;

Для типов значений (любая структура, включая int / float / double / и т. Д.) Тип передается с нулями, поэтому следующие значения эквивалентны:

int i;
int j = 0;

Однако в методе компилятор проверяет, присвоили ли вы значение вашим типам до его использования. Если вы сделаете следующее, компилятор пожалуется:

int i;
Console.WriteLine{"{0}",i);

Технически, вышесказанное должно быть в порядке - но поскольку это распространенный источник ошибок программиста, компилятор специально проверяет наличие неназначенных локальных переменных и жалуется. Однако это жалоба во время компиляции, а не проблема CLR. Вы можете сделать IL, который выполняет вышеприведенное, и он работает нормально.

...