Problem z wypisaniem listy

0

Witam, mam pewien problem.
Mam takie 2 metody:

public void dodajBibliotekarza(Bibliotekarz bibliotekarz)
        {
            
           bibliotekarze.Add(bibliotekarz);
        }

        public void wypiszBibliotekarzy()
        {
            foreach (Bibliotekarz bibliotekarz in bibliotekarze)
            {
                Console.WriteLine($"imie: {bibliotekarz.Imie} nazwisko: {bibliotekarz.Nazwisko} data zatrudnienia: {bibliotekarz.DataZatrudnienia}" +
                        $"wynagrodzenie: {bibliotekarz.Wynagrodzenie}");
            }
        }

Pierwsza ma pobierać dane z klasy Bibliotekarz w której są 3 stringi i 1 double i zapisać je do klasy bibliotekarze.
Druga ma wypisywać elemynty z tej listy.
Jednak gdy próbuję to sprawdzić takim kodem:

            Bibliotekarz k = new Bibliotekarz("A","B","C", 2);
            Biblioteka b = new Biblioteka();
            b.dodajBibliotekarza(k);
            b.wypiszBibliotekarzy();

Nie wyświetla przypisanych wartości, a jedynie puste pola.
Może mi ktoś wytłumaczyć o co chodzi?
Z góry dziękuję.

1

Nie napisałeś co chciałeś sprawdzić.
Kod (poza polskimi nazwami oraz camelCase zamiast PascalCase) wygląda prawidłowo.
Cokolwiek nie działa prawidłowo sprawdzisz to wykonując kod pod debugerem linijka po linijce.

0

@ŁF: Rzeczywiście, zakręciłem się, już poprawione.

0

Pokaż konstruktor klasy Bibliotekarz

0

@szydlak

        public Bibliotekarz()
        {
            dataZatrudnienia = "puste";
            wynagrodzenie = 0;
        }
        public Bibliotekarz(string imie_, string nazwisko_, string dataZatrudnienia_, double wynagrodzenie_) : base(imie_, nazwisko_)
        {
            imie_ = imie;
            nazwisko_ = nazwisko;
            dataZatrudnienia_ = dataZatrudnienia;
            wynagrodzenie_ = wynagrodzenie;
        }
0

@kuku4321

mozesz pokazac caly kod? w sensie klase Biblotekarz i klase z ktorej dziedziczy (bo widze ze uzywasz base)

0

@fasadin: jasne
Bibliotekarz:

    public class Bibliotekarz : Osoba
    {
        private string dataZatrudnienia;
        private double wynagrodzenie;



        public Bibliotekarz()
        {
            dataZatrudnienia = "puste";
            wynagrodzenie = 0;
        }
        public Bibliotekarz(string imie_, string nazwisko_, string dataZatrudnienia_, double wynagrodzenie_) : base(imie_, nazwisko_)
        {
            imie_ = imie;
            nazwisko_ = nazwisko;
            dataZatrudnienia_ = dataZatrudnienia;
            wynagrodzenie_ = wynagrodzenie;
        }
        public string DataZatrudnienia
        {
            get { return dataZatrudnienia; }
            set { dataZatrudnienia = value; }
        }

        public double Wynagrodzenie
        {
            get { return wynagrodzenie; }
            set { wynagrodzenie = value; }
        }
    }
}

Osoba:

    public class Osoba
    {
        protected string imie;
        protected string nazwisko;

        public Osoba()
        {
            imie = "puste";
            nazwisko = "puste";
        }

        public Osoba(string imie_, string nazwisko_)
        {
            imie_ = imie;
            nazwisko_ = nazwisko;
        }

        public string Imie
        {
            get { return imie; }
            set { imie = value; }
        }
        public string Nazwisko
        {
            get { return imie; }
            set { imie = value; }
        }

    }
}  
3
    public Osoba(string imie_, string nazwisko_)
        {
            imie_ = imie;
            nazwisko_ = nazwisko;
        }

przypisujesz tutaj argumenty funkcji do zmiennych klasy, Uzyj operatora this to wtedy sie raczej nie pomylisz ;) w sensie

To robi Twoj kod

    public Osoba(string imie_, string nazwisko_)
        {
            imie_ = this.imie;
            nazwisko_ = this.nazwisko;
        }

a chcesz

    public Osoba(string imie_, string nazwisko_)
        {
           this.imie = imie_;
           this.nazwisko =  nazwisko_ ;
        }

mozesz pokazac klase (cala) gdzie masz zdefiniowane dodajBibliotekarza oraz wypiszBibliotekarzy()?

2

BTW nie stosuj jakichś podkreślników z d**y, stosuj się do standardów języka, w którym programujesz, tym bardziej, że nie uchroniło Cię to w żaden sposób przed złym przypisaniem. Użyj auto properties, ukryj setter w celu lepszej ochrony właściwości. Używaj angielskich nazw, żeby nie tworzyć potworków typu GetImięBibliotekarza

        public string Name { get; }
        public string Surname { get; }

        public Librarian(string name, string surname)
        {
            Name = name ?? throw new ArgumentNullException(nameof(name)); // w takim przypadku this jest niepotrzebne, bo konwencje nazewnicze argumentów i właściwości różnią się
            Surname = surname ?? throw new ArgumentNullException(nameof(surname));
        }
0

@ŁF: Nie mogę nie stosować podkreślników z d**y tylko standardów, ponieważ to jest zadanie na studia i tak jest w treści.

0

@fasadin: Nadal nie działa po zmianie

    class Biblioteka : Katalog, IZarzadaniePozycjami
    {
        private string adres;
        List<Bibliotekarz> bibliotekarze = new List<Bibliotekarz>();
        List<Katalog> katalogi = new List<Katalog>();

        public Biblioteka()
        { adres = "puste"; }

        public Biblioteka(string adres_)
        { adres_ = adres; }



        public void dodajBibliotekarza(Bibliotekarz bibliotekarz)
        {
            
           bibliotekarze.Add(bibliotekarz);
        }

        public void wypiszBibliotekarzy()
        {
            foreach (Bibliotekarz bibliotekarz in bibliotekarze)
            {
                Console.WriteLine($"imie: {bibliotekarz.Imie} nazwisko: {bibliotekarz.Nazwisko} data zatrudnienia: {bibliotekarz.DataZatrudnienia}" +
                        $"wynagrodzenie: {bibliotekarz.Wynagrodzenie}");
            }
        }

        public void wypiszWszystkiePozycje()
        {
            foreach (Katalog katalog in katalogi)
            {
                foreach (Pozycja pozycja in katalog.pozycje)
                {
                    Console.WriteLine($"tytul: {pozycja.Tytul} rok wydania: {pozycja.RokWydania} Wydawnictwo: {pozycja.Wydawnictwo}");
                }
            }
        }

        public Pozycja znajdzPozycjepoId(int id)
        {
            foreach (Katalog katalog in katalogi)
            {
                if (katalog.pozycje.Exists(p => p.Id == id))
                    {
                    return katalog.pozycje.SingleOrDefault(p => p.Id == id);
                }
            }
            return new Ksiazka();
        }

        public Pozycja znajdzPozycjePoTytule(string tytul)
        {
            foreach (Katalog katalog in katalogi)
            {
                if (katalog.pozycje.Exists(p => p.Tytul == tytul))
                    {
                    return katalog.pozycje.SingleOrDefault(p => p.Tytul == tytul);
                }
            }
            return new Ksiazka();
        }
        public void dodajPozycje(Pozycja pozycja, string dzialTematyczny)
        {
            var katalog = katalogi.SingleOrDefault(k => k.DzialTematyczny == dzialTematyczny);
            katalog.dodajPozycje(pozycja);
        }
        public void dodajKatalog(Katalog katalog)
        {
            katalogi.Add(katalog);
        }
    }
}
1

IMO powinienes zastosowac sie do rad @ŁF nawet jezeli jest w poleceniu na studia, pokreslenia oraz nazewnictwo sa z d**y (podkreslenia sie uzywa do prywatnych atrybutow klasy a nie parametrow funkcji oraz przed nazwa zmienna a nie po, ale nie o tym)

wiec przeanalizujmy co sie dzieje w tym momencie (pisze na podstawie tego co wkleiles tutaj)

  Bibliotekarz k = new Bibliotekarz("A","B","C", 2);
            Biblioteka b = new Biblioteka();
            b.dodajBibliotekarza(k);
            b.wypiszBibliotekarzy();

zostaje wywolany ten konstruktor

public Bibliotekarz(string imie_, string nazwisko_, string dataZatrudnienia_, double wynagrodzenie_) : base(imie_, nazwisko_)
        {
            imie_ = imie;
            nazwisko_ = nazwisko;
            dataZatrudnienia_ = dataZatrudnienia;
            wynagrodzenie_ = wynagrodzenie;
        }

wiec w tej kolejnosci

  1. wywolujesz bazowy konstruktor
public Osoba(string imie_, string nazwisko_)
       {
           imie_ = imie;
           nazwisko_ = nazwisko;
       }

ktory nic nie robi
nastepnie instrukcje sa wykonywane z konstruktora Biblotekarz ktory... nic nie robi (bo przypisujesz argumenty do wartosci pol klasy, wiec nic nie jest ustawiane w obiekcie/klasie)

nastepnie dodajesz obiekt k ktory ma puste wlasciwosci i nastepnie je wyswietlasz (te puste wlasciwosci)

0

@fasadin: A bibliotekarze.Add nie dodaje tych pól do listy bibliotekarze? Możesz podpowiedzieć jak to zmienić?

1

bibliotekarze.Add czyli inaczej List<T>.Add(T) dodaje obiekt do listy i to robisz. Nie wiem dlaczego myslisz ze Add mialoby dodawac pola klasy do obiektu

Najlepiej zmienic to w taki sposob jak napisal @ŁF (i tez ja preferuje takie rozwiazanie) lub tak jak CI napisalem wczesniej uzyj operatora this (tak by pole z this bylo po lewej a nie po prawej stronie)

0

@fasadin @ŁF f Ok. Bardzo wam dziękuję, wszystko działa

2
        public Biblioteka(string adres_)
        { adres_ = adres; }

WTF? Czy Ty rozumiesz co robisz? Nie możesz użyć losowych zmiennych w losowej kolejności licząc na to, że uda się przypisać do pola klasy wartość argumentu konstruktora. Myśl co robisz. Nie myślisz - nie rób, wróć do problemu za pół godziny jak głowa odpocznie.

Debuguj samodzielnie swoje programy, aby znaleźć powód własnych błędów. Polecam nieco leciwy, ale w swoim meritum nadal aktualny artykuł Debugowanie.

        public Pozycja znajdzPozycjepoId(int id)
        {
            foreach (Katalog katalog in katalogi)
            {
                if (katalog.pozycje.Exists(p => p.Id == id))
                    {
                    return katalog.pozycje.SingleOrDefault(p => p.Id == id);
                }
            }
            return new Ksiazka();
        }

WTF? Nie znaleziono, to zwracaj null albo wal wyjątkiem zamiast po cichu zwracać nieprawidłowy wynik. Wyobraź sobie użycie takiej wyszukiwarki: wpisujesz id (BTW skąd masz znać id wyszukiwanej ksiażki? Wyszukuje się zwykle po autorze i/lub tytule), wyskakuje Ci książka o pustych danych. Coś chyba nie tak, co?
Nazewnicto znowu fatalne. znajdźPozycjepoId wyglada jakbyś nie mógl się zdecydować gdzie duża litera, a gdzie mała, więc rzucałeś monetą. ZnajdźPozycjęPoId (tak tak, C# obsługuje UTF w nazwach elementów), ale i tak oczy bolą, bo powinno być GetPositionById, albo - jeśli jesteś w klasie PositionService - GetById.
Do tego niespójne wcięcia. Piszesz w notatniku, czy w porządnym IDE (np. VS)? IDE by default na bieżąco formatuje to co piszesz, więc trzeba się naprawdę postarać, żeby spieprzyć formatowanie/wcięcia.
Koejna sprawa: jeśli katalog.pozycje.Exists zwróci true, ale masz dwie pozycje o tym samym id (mało możliwe, ale jednak), to dostaniesz wyjątek. Skoro Exists zwróciło true, to ani nie potrzebujesz Single (użyj First, które jest szybsze i nie zaskoczy Cię wyjątkiem), ani tym bardziej OrDefault, bo przecież sprawdziłeś linijkę wcześniej, że książka istnieje.
Całość da się zrobić prawidłowo w jednej linijce: public Position GetById(int id) => Catalogs.SelectMultiple(c => c.Positions).FirstOrDefault(p => p.Id == id);.

        public void dodajPozycje(Pozycja pozycja, string dzialTematyczny)
        {
            var katalog = katalogi.SingleOrDefault(k => k.DzialTematyczny == dzialTematyczny);
            katalog.dodajPozycje(pozycja);
        }

Jeśli dzialTematyczny (brrr) nie istnieje, to dostaniesz null reference exception. Mam wrażenie, że nie rozumiesz, co robisz. SingleOrDefault nazywa się tak jak się nazywa, bo zwraca null, jeśli nic nie znajdzie. A linijkę niżej radośnie odwołujesz się do zwróconej wartości. Tak się nie robi. Wyjątek ma być rzucony jak najbliżej miejsca, które spowodowało błąd, inaczej spędzisz wieki na szukaniu powodu tegoż wyjatku. Zatem var catalog = Catalogs.First(c => c.SectionTopic == sectionTopic); albo var catalog = Catalogs.FirstOrDefault(c => c.SectionTopic == sectionTopic) ?? throw new ArgumentException($"Catalog with section topic {sectionTopic} not found");. Warto się też zabezpieczyć przed ewentualnym dodaniem nulla do listy, bo potem - ponownie - będziesz dociekać dlaczego kod wywala się z NRE w kompletnie innym, pozornie niezwiązanym miejscu.

        public void dodajKatalog(Katalog katalog)
        {
            katalogi.Add(katalog);
        }

Zabezpiecz się przed null: public void AddCatalog(Catalog catalog) => catalogs.Add(catalog ?? throw new ArgumentNullException(nameof(catalog)));.

I tak dalej, i tak dalej...

1

Każdy mówi, "nie powinno się stosować łączenia polskich i angielskich wyrazów w nazwach, ale ..." po czym niemal wszyscy świadomie to robią. Tak więc zgodnie z tym co mawiał Pan Prof. Bralczyk - jeśli forma nieprawidłowa się przyjęła powszechnie, to należy uznać, że stała się formą prawidłową ;-)
Taka dygresja z mojej strony.

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