2009-06-04 8 views
12

Czy jest jakaś różnica, czy zainicjować zmienną całkowitą jak:C# Inicjalizacja zmiennej Pytanie

int i = 0; 
int i; 

Czy traktować to kompilator lub CLR jako samo? IIRC, myślę, że oboje traktowani są jak to samo, ale nie mogę znaleźć tego artykułu.

+11

_Fields_ są zawsze automatycznie inicjowane do wartości domyślnej typu pola, która w przypadku int wynosi zero. Pola są uważane za zdecydowanie przypisane; możesz przeczytać ich zawartość nawet przed wyraźnym przydziałem. _Lokalne_ nie są uważane za zdecydowanie przypisane; jesteś zobowiązany do zrobienia czegoś, co przypisuje wartość lokalnego, zanim jego zawartość zostanie odczytana. Szczegółowe informacje znajdują się w sekcji "określony przydział" w specyfikacji C#. –

Odpowiedz

6

Spojrzałem na IL (używając ildazmu) i jego prawdziwość, że tylko int ustawione na 0 jest naprawdę ustawione na 0 w konstruktorze.

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

Generuje:

.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 
+0

Ale czy nie jest możliwe, że ctor dla tej klasy obsługuje inicjowanie zmiennych dla tych zmiennych, które nie są jawnie przypisane? –

+8

Michael: pola są inicjowane do wartości domyślnych (zero) przez _memory manager_, a nie przez _constructor_. –

+0

Podziękowania dla Eric Lippert za wyjaśnienie. Chciałbym móc przyznać rację jednej lub kilku osobom, które brały udział w tej dyskusji. Zawsze jak zwykle odchodzę z większą wiedzą, że tu przybyłem;) – coson

4

Tak, to prawie to samo.

Można odwołać się do tego artykułu na Coding Horror

+0

+1 dla linku. Ciekawa dyskusja na ten temat. – CAbbott

14

Jeśli zmienna i jest zmienną instancji, to będzie automatycznie przypisać wartość 0. Jeśli jest to zmienna lokalna w metodzie, jest niezdefiniowana, więc przed jej użyciem musisz przypisać jej wartość.

Na przykład

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); 
     } 
    } 
} 

Powyższe nie kompilacji ponieważ I2 nieprzypisany. Jednak poprzez przypisanie 0 do i2, tj

int i2 = 0; 

i kompilacji, a następnie uruchomiony, pokaże, że oba są teraz przypisane 0.

+0

int jest strukturą nie klasą. structs mają domyślną wartość, podczas gdy klasy są domyślnie nul. –

+0

@Matthew Whited, nie miał na myśli, że to była klasa. Mówił na poziomie "klasy", co naprawdę oznacza zmienną instancji. Zmieniłem to dla wyjaśnienia. – mmcdole

0

każdej chwili utworzyć typ w języku C#, automatycznie pobiera wypełniane wyściełane zera. W przypadku klasy (typ referencyjny) oznacza to wskaźnik zerowy. Więc, technicznie, za każdym razem gdy pracujesz z klas, następujące są identyczne:

MyClass class; 
MyClass class2 = null; 

Z typów wartości (dowolny struktury, w tym int/pływaka/podwójne/etc), typ przepuszcza zerami, więc następujące są równoważne:

int i; 
int j = 0; 

jednak w metodzie sprawdza kompilatora, aby zobaczyć, jeśli już przypisana wartość do swoich typach przed użyciem. Jeśli nie następuje, kompilator będzie narzekać:

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

Technicznie powyższe powinno być w porządku - ale ponieważ jest to częstym źródłem błędu programisty, kompilator specjalnie sprawdza nieprzypisanych zmiennych lokalnych i narzeka. Jest to jednak skarga dotycząca kompilacji, a nie kwestia CLR. Możesz zrobić IL, który robi powyższe, i działa dobrze.

0

Są to odpowiednik tylko dla pól zmiennych (klasa). Do pól są automatycznie przypisywane wartości domyślne, gdy klasa jest inicjowana. Wewnątrz metody lub właściwości nieprzypisana zmienna pozostaje nieprzypisana i spowoduje błąd kompilatora, jeśli spróbujesz uzyskać dostęp do jego wartości.

1

Przy wszystkich tych rozmowach warto wspomnieć o słowach kluczowych "default" w języku C#.

tj. int i; jest równoważna int i = default(int); co odpowiada int i = 0; i MyClass o = default(MyClass); jest równoważna MyClass o = null;

Jest to szczególnie istotne przy użyciu metod LINQ takich jak .SingleOrDefault() bo zawsze można użyć następujących aby kod był bardziej czytelny:

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

i

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

tutaj reakcje są różne rodzaj mylące, w tym th e artykuł na stronie "Coding Horror".

Kompilator zoptymalizuje kod w celu usunięcia wszystkich "niepotrzebnych" inicjalizacji po skonfigurowaniu do optymalizacji wygenerowanego kodu. Zauważ, że jest to domyślne zachowanie podczas kompilacji w trybie "Release".

Ja na przykład uważam, że zawsze warto zainicjować wszystkie zmienne. Uderzenie wydajności będzie minimalne w trybie debugowania i żadne w trybie zwolnienia, ale zyski jawnie ustawionych zmiennych będą ogromne dla każdego, kto będzie utrzymywał kod w przyszłości, w lepszym stylu "dokumentowania kodu z kodem". Pamiętam tego bardzo doświadczonego współpracownika, który myślał, że domyślną wartością Int32 jest Int32.MinValue zamiast 0. Tego typu zamieszanie ma zawsze miejsce w przypadku implicited w kodzie i, w moim przypadku, powinno się ich unikać w większości przypadków.