Вопрос с переменной инициализацией С#

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

int i = 0;
int i;

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

Ответ 1

Я посмотрел на IL (используя ildasm) и его true, что только 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

Ответ 2

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

Например:

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.

Ответ 3

Да, это в значительной степени одно и то же.

Вы можете обратиться к этой статье в Ужас кодирования

Ответ 5

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

т.е. 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
}

Ответ 6

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

MyClass class;
MyClass class2 = null;

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

int i;
int j = 0;

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

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

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

Ответ 7

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

Ответ 8

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

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

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