2010-07-21 35 views
37

Mam bardzo początku pytanie C#. Załóżmy, że mam klasę o nazwie GameObject, i chcę utworzyć tablicę z GameObject podmiotów. Mógłbym napisać kod taki jak:Jak zadeklarować tablicę obiektów w C#

GameObject[] houses = new GameObject[200]; 

Kompilator narzeka (zakładając z powodu nieprawidłowej składni). Ponieważ jest to rozwój XNA, załadować moje tekstury w metodzie LoadContent() następująco:

houses[0].Model = Content.Load<Model>("Models\\Building_01 Windowed"); 

gdzie houses[0] powinny być GameObject i mogą być ładowane w ten sposób, ale kompilator generuje ten błąd:

"Use the "new" keyword to create an object instance"

"Check to determine if the object is null before calling the method"

Coś musi być nie tak z moją inicjalizacją.

+3

Oprócz twoich odstępów, nie ma w tym nic złego. Powiedz nam konkretny błąd? – Noldorin

+4

Kompilator nie ** powiedział, że coś jest nie tak. Kompilator podał konkretny komunikat o błędzie lub wiadomości. Edytuj swoje pytanie, aby uwzględnić szczegóły. –

+2

Cóż naprawić * coś * następnie nie mogę odczytać umysłu kompilatora. Jak możesz oczekiwać jakiejś realnej odpowiedzi na takie pytanie? –

Odpowiedz

45

Problem polega na tym, że zainicjowano układ , ale nie jego elementy ; wszystkie są zerowe. Więc jeśli spróbujesz odwołać się do houses[0], będzie to null.

Oto wielki mały metoda pomocnika można napisać dla siebie:

T[] InitializeArray<T>(int length) where T : new() 
{ 
    T[] array = new T[length]; 
    for (int i = 0; i < length; ++i) 
    { 
     array[i] = new T(); 
    } 

    return array; 
} 

Następnie można zainicjować tablicę houses jak:

GameObject[] houses = InitializeArray<GameObject>(200); 
+1

Bardzo dobry pomocnik, dzięki, Dan. W pewnym sensie briandeaded, gdy tworzyłem tablicę. Ale nadal uważam, że kompilator takich nowoczesnych langug powinien być bardziej sprytny. – Kevin

+6

@Robert: Nie zawsze chcesz zainicjować wszystkie obiekty. –

0

Wszystko, co masz dobrze wygląda.

Jedyne, co mogę wymyślić (bez wyświetlenia komunikatu o błędzie, który powinien być podany), to że GameObject potrzebuje domyślnego konstruktora (bez parametru).

+0

To nie powinno powodować komunikatu o błędzie podczas tworzenia ich tablicy ... – thecoop

+1

Nie powinien potrzebować konstruktora bez parametrów, aby zadeklarować prostą tablicę. Nie inicjalizuje go z rzeczywistymi instancjami, ale ma wartość null. – drharris

+0

D'oh! I mylić mój C# i C++ ponownie ... –

8

Tworzysz tablicę referencji zerowych. Powinieneś zrobić coś takiego:

for (int i = 0; i < houses.Count; i++) 
{ 
    houses[i] = new GameObject(); 
} 
+0

Powinien być "domy.Length' zamiast' domy.Count ". –

+2

Ups! Nie używam tablic - dlaczego? Używam jakiejś kolekcji. Kolekcje mają właściwość Count. –

+0

Ponieważ tablice będą szybsze w niektórych sytuacjach. –

1

Domyślam się, że GameObject jest typem referencyjnym. Domyślnie dla typów odniesienia jest null => masz tablicę zer.

Należy zainicjować każdy element tablicy osobno.

houses[0] = new GameObject(..); 

Tylko wtedy można uzyskać dostęp do obiektu bez błędów kompilacji.

Więc można jednoznacznie initalize tablicę:

for (int i = 0; i < houses.Length; i++) 
{ 
    houses[i] = new GameObject(); 
} 

czy można zmienić GameObject do typu wartości.

+0

Nadal nie zademonstrowałeś, w jaki sposób deklaruje on tablicę domów. – David

0

The powodu tak się dzieje dlatego, inicjowanie tablicę robi nie inicjalizuj każdego elementu w tej tablicy. Najpierw musisz ustawić houses[0] = new GameObject(), a następnie zadziała.

+0

Poza tym, że nadal musi najpierw stworzyć tablicę domów, której jeszcze nie był w stanie zrobić. – David

6

Dzięki LINQ można przekształcić tablicę niezainicjowanych elementów w nowy zbiór utworzonych obiektów za pomocą jednego wiersza kodu.

var houses = new GameObject[200].Select(h => new GameObject()).ToArray(); 

Faktycznie, można użyć dowolnego innego źródła dla tego, nawet generated sequence liczb całkowitych:

var houses = Enumerable.Repeat(0, 200).Select(h => new GameObject()).ToArray(); 

jednak pierwszy przypadek wydaje mi się bardziej czytelne, choć rodzaj oryginalnej sekwencji nie jest ważne .

+2

Myślę, że drugi przypadek jest znacznie bardziej czytelny i oczywisty, co robi ... i jak powiedziałeś, w pierwszym przykładzie typ oryginalnej sekwencji nie jest ważny, co jest bardzo mylące dla każdego, kto ją czyta. To tylko ostrzeżenie dla kogokolwiek innego używającego tego, Enumerable.Repeat może mieć wpływ na wydajność, jeśli piszesz krytyczny kod wydajności. Jeśli nie jesteś, to myślę, że to świetne rozwiązanie. – Rocklan

+0

To dobry punkt! Drugi przypadek jest bardziej poprawny, jak opisałeś, ale w pierwszym można "odgadnąć" cel linii od samego początku. – Eugene

0

Musisz zainicjować elementy obiektów tablicy.

GameObject[] houses = new GameObject[200]; 

for (int i=0;`i<house` i<houses.length; i++) 
{ houses[i] = new GameObject();} 

Oczywiście elementy inicjalizowane są selektywnie za pomocą różnych konstruktorów w innym miejscu, zanim się do nich odwołają.

Powiązane problemy