Object reference not set to an instance of an object - konstruktory i tablice

0

Witam. Pogłębiając swoją wiedzę na temat c# wziąłem "na warsztat" ENUM. Pisząc sobie prosty program, chciałem stworzyć obiekty z wykorzystaniem tablicy:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Program
{
    class main
    {
        public enum Dzial { Pracownik_Produkcji, Kontroler_Jakosci, Kierownik, Sprzataczka, Dyrektor };

        class Pracownik
        {
            public string imie;
            public string nazwisko;
            public int wiek;
            public Dzial stanowisko;

            public void Dodaj(string _imie, string _nazwisko, int _wiek, Dzial _stanowisko)
            {
                imie = _imie;
                nazwisko = _nazwisko;
                wiek = _wiek;
                stanowisko = _stanowisko;
            }

            public void Wyswietl()
            {
                 Console.WriteLine(imie + " " + nazwisko + ", " + wiek + " (" + stanowisko + ")");
            }

        }

        public static void Main(string[] Args)
        {
            Pracownik[] czlowiek = new Pracownik[2];
            czlowiek[0].Dodaj("Stefan", "Stefański", 35, Dzial.Kontroler_Jakosci);
            czlowiek[1].Dodaj("Mariano", "Italiano", 35, Dzial.Dyrektor);
            czlowiek[0].Wyswietl();
            czlowiek[1].Wyswietl();

            Console.ReadKey();
        }
    }

}

Niestety. Program wywalił mi błąd. O ile konstrutory by były bez tablic to błędów by nie było, o tyle w przypadku wykorzystania tablic pojawia się problem:

title

Gdzie popełniam błąd? Z góry dzięki za odpowiedź.

1

czlowiek[0] jest nullem (nie ma człowieka pod tym indexem :D), a próbujesz na nim wywołać metodę Dodaj

Jeżeli już tak bardzo chcesz to zrobić w ten sposób (chociaż można to zrobić o wiele lepiej) to prędzej coś typu:

Pracownik[] czlowiek = new Pracownik[2];
var pracownik = new Pracownik();
pracownik.Dodaj("stefan", "stefański", 15, Dzial.Dyrektor);
czlowiek[0] = pracownik;
czlowiek[0].Wyswietl();

ale już lepiej byłoby gdybyś zdefiniował konstruktor przyjmujący np. string imie, string nazwisko, int wiek, Dzial stanowisko i wtedy kod skróciłby się do czegoś takiego:

Pracownik[] czlowiek = new Pracownik[2];
czlowiek[0] = new Pracownik("stefan", "stefański", 15, Dzial.Dyrektor);
czlowiek[0].Wyswietl();
3

Nie inicjalizujesz obiektów klasy Pracownik. Inicjalizujesz tylko tablice tych obiektów. Po

Pracownik[] czlowiek = new Pracownik[2];

Dodaj:

czlowiek[0] = new Pracownik();
czlowiek[1] = new Pracownik();

albo lepiej wywal te metode Dodaj i pracownika twórz w konstruktorze

 class Pracownik
            {
                public string imie;
                public string nazwisko;
                public int wiek;
                public Dzial stanowisko;

                public Pracownik(string _imie, string _nazwisko, int _wiek, Dzial _stanowisko)
                {
                    imie = _imie;
                    nazwisko = _nazwisko;
                    wiek = _wiek;
                    stanowisko = _stanowisko;
                }

                public void Wyswietl()
                {
                    Console.WriteLine(imie + " " + nazwisko + ", " + wiek + " (" + stanowisko + ")");
                }

            }

            public static void Main(string[] Args)
            {
                var czlowiek = new Pracownik[] 
                {
                    new Pracownik("Stefan", "Stefański", 35, Dzial.Kontroler_Jakosci),
                    new Pracownik("Mariano", "Italiano", 35, Dzial.Dyrektor)
                };
               
                czlowiek[0].Wyswietl();
                czlowiek[1].Wyswietl();

                Console.ReadKey();
            }
0

Dzięki za porady. Zrozumiałem już swój błąd, jednocześnie wywaliłem klasę do osobnego pliku, jak mi ktoś kiedyś zasugerował na tym forum. Kod wygląda tak i działa poprawnie:

Pracownik.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Program
{
    public enum Dzial { Pracownik_Produkcji, Kontroler_Jakosci, Kierownik, Sprzataczka, Dyrektor };
    public class Pracownik
    {  
        public string imie;
        public string nazwisko;
        public int wiek;
        public Dzial stanowisko;

        public Pracownik(string _imie, string _nazwisko, int _wiek, Dzial _stanowisko)
        {
            imie = _imie;
            nazwisko = _nazwisko;
            wiek = _wiek;
            stanowisko = _stanowisko;
        }
        public void Wyswietl()
        {
            Console.WriteLine(imie + " " + nazwisko + ", " + wiek + " (" + stanowisko + ")");
        }

    }
}

Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Program
{

    class main
    {
        public static void Main(string[] Args)
        {
            Pracownik[] czlowiek = new Pracownik[2];
            czlowiek[0] = new Pracownik("Stefan", "Stefański", 35, Dzial.Dyrektor);
            czlowiek[1] = new Pracownik("Mariano", "Italiano", 35, Dzial.Kierownik);
            czlowiek[0].Wyswietl();
            czlowiek[1].Wyswietl();

            Console.ReadKey();
        }
    }

}

Rezultat:

title

1

Aż miło patrzeć jak ktoś przykłada się do nauki.

Uwaga z mojej strony: klasa Pracownik nie powinna mieć metody Wyświetl. Powinieneś przeciążyć metodę ToString() i w niej zwracać tego stringa. Dodatkowo w C# jest dobrodziejstwo zwane interpolacją stringów. Dzięki temu kod wygląda o wiele lepiej:

Pracownik.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Program
{
    public enum Dzial { PracownikProdukcji, KontrolerJakosci, Kierownik, Sprzataczka, Dyrektor };
    public class Pracownik
    {  
        public string Imie { get; }
        public string Nazwisko { get; }
        public int Wiek { get; }
        public Dzial Stanowisko { get; }

        public Pracownik(string imie, string nazwisko, int wiek, Dzial stanowisko)
        {
            Imie = imie;
            Nazwisko = nazwisko;
            Wiek = wiek;
            Stanowisko = stanowisko;
        }

        public override string ToString()
            => $"{Imie} {Nazwisko}, {Wiek} ({Stanowisko})";
    }
}

Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Program
{
    class main
    {
        public static void Main(string[] Args)
        {
            var pracowieki = new[]
            {
                new Pracownik("Stefan", "Stefański", 35, Dzial.Dyrektor),
                new Pracownik("Mariano", "Italiano", 35, Dzial.Kierownik)
            };
            
            foreach (var pracownik in pracowieki)
                Wyswietl(pracownik);

            Console.ReadKey();
        }

        private static void Wyswietl(Pracownik pracownik)
            => Console.WriteLine(pracownik);
    }
}

Dodatkowo:

  • uprościłem zapis tablicy.
  • wykorzystałem pętlę do wyświetlania poszczególnych pracowników - jak dodasz trzeciego nie będzie trzeba tego zmieniać.
  • poprawiłem enuma (wg konwencji nie używamy podkreślników).
  • zmieniłem pola na właściwości, bo tych przyjęło się używać i poprawiłem ich nazwy (publiczne pola i właściwości pisze się z wielkiej litery - wg konwencji). Zauważ też, że nie mają settera - to powoduje, że są tylko do odczytu.
  • użyłem skróconego zapisu dla metod jednolinijkowych.
  • poprawiłem nazwę zmiennej tablicowej. Nie wiem dlaczego używasz zmiennej czlowiek dla klasy pracownik. To nie jest to samo ;P

Jeżeli znasz angielski to zacznij go używać w kodzie - gdy się używa naszego pięknego ojczystego języka to wychodzi dziwaczny polglish, który już tak literacko nie wygląda. Jeżeli nie znasz angielskiego to jeżeli chciałbyś kiedyś pracować jako programista, to jest on do pracy nie-zbę-dny.

To chyba wszystko. Kod może się nie kompilować, bo pisałem z palca, ale będą to raczej pierdoły typu brak nawiasu czy średnika.
Jeżeli coś jest niejasne - pytaj, wyjaśnimy.

1 użytkowników online, w tym zalogowanych: 0, gości: 1