2011-09-23 4 views
10

Mam jedną obserwację dotyczącą struct. Kiedy zadeklarować obiektu Struct i jeśli nie zainicjować struct to daje mi poniższy błąd - „Korzystając z nieprzydzielonej zmiennej lokalnej empStruct”Kompilator podaje błąd, gdy struct nie jest zainicjalizowany i jeśli spróbujemy uzyskać dostęp do właściwości, ale nie ze zmienną

PSeduo Code

struct EmpStruct 
{ 
    private int firstNumber; 
    public int FirstNumber 
    { 
     get { return firstNumber; } 
     set { firstNumber = value; } 
    } 

    public int SecondNumber; 

} 

Program.cs-

EmpStruct empStruct; 
empStruct.FirstNumber = 5; 

Ale kiedy deklaruję publiczną zmienną, powyższy kod działa.

EmpStruct empStruct; 
empStruct.SecondNumber; 

Moje pytanie brzmi: dlaczego kompilator nie podaje błędu, gdy próbuję uzyskać dostęp do zmiennej (w przypadku klasy spowoduje to błąd).

+3

Ktokolwiek zaniedbuje wszystkie odpowiedzi, pozostawia komentarze, dlaczego są nieprawidłowe. Przebudowuję je, ponieważ mają sens w oparciu o post Punita ... –

+1

@bemused: Wszystkie są złe. I zostawiłem komentarze wyjaśniające dlaczego. – jason

Odpowiedz

11

W tej nitce jest ogromna ilość zamieszania.

Zasada jest taka: dopóki wszystkie pola instancji obiektu struct nie zostaną definitywnie przypisane, nie można wywoływać żadnych właściwości ani metod w instancji.

Dlatego Twój pierwszy blok kodu nie zostanie skompilowany. Uzyskujesz dostęp do nieruchomości bez definitywnego przypisania wszystkich pól.

Drugi blok kodu jest kompilowany, ponieważ można uzyskać dostęp do pola bez przypisywania wszystkich pól.

Jednym ze sposobów zdecydowanie przypisać struct znaczy

EmpStruct empStruct = new EmpStruct(); 

To wywołuje domyślny konstruktor bez parametrów dla EmpStruct które z pewnością przypisać wszystkich pól.

Odpowiednią sekcję specyfikacji stanowi § 5.3 na temat Przypisania określonego. Iz przykład w §11.3.8

nr funkcji członka instancji (w tym zestaw akcesorów dla właściwości X i Y) może być wywoływana aż wszystkie pola struct są zbudowane zostały definitywnie przypisane.

Byłoby bardziej pomocna (hm, Eric Lippert!), Czy komunikat o błędzie kompilatora były wzdłuż linii

Zastosowanie pewno nie przypisanej zmiennej lokalnej empStruct.

Następnie staje się jasne, czego szukać w specyfikacji lub na Google.

Teraz należy pamiętać, że zdefiniowano zmienną strukturę. To jest niebezpieczne i złe. Nie powinieneś tego robić. Zamiast tego dodaj publiczny konstruktor, który pozwala definitywnie przypisać firstNumber i secondNumber i usunąć publiczny ustawiacz z EmpStruct.FirstNumber.

+0

+1, dobry dostęp do przywracających własności! – sll

+0

Dzięki za wyczyszczenie nici w górę. Myślę, że to było sformułowanie pytania, które wszystkich zdezorientowało. –

+0

dzięki sens – Punit

3

pola dotyczące C# język Specyfikacja mówi:

10.5.4 inicjalizacji Pole

Wartość początkowa polu, czy to statyczne pole lub pola przykład, jest domyślna wartość (§5.2) typu pola. Jest nie można obserwować wartość pola przed tym domyślnie inicjalizacji wystąpiło, a pole jest zatem nigdy „niezainicjowany

11.3.4 Wartości domyślne

Jednakże, ponieważ structs są typami wartości, które nie mogą być puste, domyślną wartością struct jest wartość tworzona przez ustawienie wszystkich pól wartości typu na ich wartość domyślną i wszystkich pól typu odniesienia na null. Domyślna wartość struct odpowiada wartości zwróconej przez domyślny konstruktor struktury (01.2).

PS: w przypadku klasy daje błąd, ponieważ wartość referencyjna Typ domyślnie jest null

+0

To nie ma znaczenia. Nie wyjaśnia przyczyny błędu. – jason

+0

@Jason: Jest to istotne z punktu widzenia pola i klasy, ale nie jest to błąd związany z właściwościami. Nadal nie mogę znaleźć odpowiedzi w specyfikacji – sll

+0

Przykro mi, to nie ma znaczenia. Przyczyna błędu ma związek z brakiem określonego przypisania do "EmpStruct". Fragmenty cytowanej specyfikacji nie zawierają odniesienia do określonego przypisania. Zobacz §5.3 i §11.3.8. – jason

1

W pierwszym przykładzie kod nie działa, ponieważ zmienne lokalne muszą zostać zainicjowane przed można z nich korzystać . Nie ma wartości "domyślnej"; muszą być najpierw zainicjowane. Zawsze musisz zainicjować każdą zmienną lokalną, zanim będziesz mógł z niej korzystać. Na przykład:

EmpStruct empStruct = new EmpStruct(); 
empStruct.FirstNumber = 5; 

Pola w klasie nie mają tego samego ograniczenia. Jeśli nie zainicjujesz ich jawnie, zostaną one automatycznie zainicjowane z wartościami domyślnymi. W efekcie środowisko wykonawcze automatycznie wywołuje "new EmpStruct()" na polu w twojej klasie. Dlatego twój drugi przykład działa.

+0

To nie ma żadnego sensu.Dlaczego kompilator miałby wywoływać 'new EmpStruct' w drugim bloku, ale nie pierwszy? Ta odpowiedź nie wyjaśnia, dlaczego istnieje różnica między dwoma blokami kodu. – jason

+0

Ah ... Myślę, że miałem trudności ze zrozumieniem pierwotnego pytania ... Myślałem, że mówił o użyciu struct jako zmiennej lokalnej vs przy użyciu struct jako pola. –

1

Kilka próbki kodu może pomóc wyjaśnić to lepiej:

// This works because you assign both fields before accessing anything 
EmpStruct empStruct; 
empStruct.SecondNumber = 2; 
empStruct.firstNumber = 1; // I made this public 
empStruct.FirstNumber = 3; 
Console.WriteLine(empStruct.FirstNumber); 
Console.WriteLine(empStruct.SecondNumber); 

// This fails because you can't use properties before assigning all the variables 
EmpStruct empStruct; 
empStruct.SecondNumber = 2; 
empStruct.FirstNumber = 3; 

// This works because you are only accessing a field that the compiler knows you've assigned 
EmpStruct empStruct; 
empStruct.SecondNumber = 2; 
Console.WriteLine(empStruct.SecondNumber); 

// This fails because you haven't assigned the field before it gets accessed. 
EmpStruct empStruct; 
Console.WriteLine(empStruct.SecondNumber); 

Chodzi o to, że kompilator nie wie dokładnie, co się stanie, gdy pole przypisać. Ale gdy przypisujesz właściwość, może ona uzyskać dostęp do dowolnej liczby innych pól na struct. Kompilator nie wie na pewno. Wymaga to, aby wszystkie pola były przypisane, zanim uzyskasz dostęp do właściwości.

Powiązane problemy