Zapewnienie odporności aplikacji na błędy oraz efektywne zarządzanie zbiorami danych w pamięci przy użyciu mechanizmów generycznych.
Student demonstruje umiejętność łączenia zaawansowanych kolekcji generycznych (Dictionary, List) z mechanizmami bezpiecznej obsługi błędów. Zadanie ma na celu pokazanie praktycznego zastosowania własnych klas wyjątków oraz wykorzystania technologii LINQ do szybkiego filtrowania i agregacji danych w strukturach słownikowych. Student rozumie, jak zarządzać cyklem życia zgłoszenia w systemie informatycznym, dbając o spójność danych.
Zostałeś oddelegowany do stworzenia modułu serwerowego dla centrum zgłoszeń technicznych w firmie telekomunikacyjnej. System musi przechowywać aktywne zgłoszenia w strukturze słownikowej (Dictionary), gdzie kluczem jest unikalny identyfikator zgłoszenia, a wartością obiekt klasy Zgloszenie. Każde zgłoszenie posiada listę (List) wpisów w historii, dokumentującą kroki podjęte przez techników. Twoim zadaniem jest zapewnienie, aby każda próba odczytu nieistniejącego zgłoszenia lub próba przypisania błędnego statusu kończyła się wyrzuceniem dedykowanego wyjątku SerwisException. Program w konsoli powinien umożliwić dodawanie zgłoszeń, aktualizację ich opisów oraz generowanie raportów statystycznych. Musisz wykorzystać LINQ, aby w ułamku sekundy odnaleźć wszystkie zgłoszenia o statusie "Pilne" lub te, które nie były aktualizowane od dłuższego czasu. Całość aplikacji musi być zabezpieczona blokami try-catch, które w sposób czytelny informują operatora o przyczynie problemu, na przykład o dublowaniu się numerów ID. Projekt ten stanowi fundament pod budowę systemów klasy Helpdesk i Service Management. Finalny kod musi gwarantować, że nawet w sytuacjach awaryjnych system nie ulegnie zawieszeniu i wyświetli precyzyjne logi diagnostyczne.
using System; using System.Collections.Generic; using System.Linq; // Własny wyjątek class SerwisException : Exception { public SerwisException(string msg) : base(msg) { } } class Zgloszenie { public int Id { get; set; } public string Opis { get; set; } public string Status { get; set; } } class Program { static Dictionary<int, Zgloszenie> baza = new Dictionary<int, Zgloszenie>(); static void Dodaj(int id, string opis) { if (baza.ContainsKey(id)) throw new SerwisException($"ID {id} już istnieje w systemie!"); baza.Add(id, new Zgloszenie { Id = id, Opis = opis, Status = "Nowe" }); } static void Main() { try { Dodaj(101, "Awaria routera"); Dodaj(102, "Błąd logowania"); Dodaj(101, "Duplikat"); // Tu wystąpi błąd } catch (SerwisException ex) { Console.WriteLine($"BŁĄD SYSTEMU: {ex.Message}"); } finally { Console.WriteLine("Zakończono operację na słowniku."); } // Prosty LINQ var wyniki = baza.Values.Where(z => z.Opis.Contains("Awaria")); Console.WriteLine("\nWyniki wyszukiwania:"); foreach (var z in wyniki) Console.WriteLine($"[{z.Id}] {z.Opis} ({z.Status})"); } }
Zapoznanie studentów z hierarchią wyjątków wbudowanych w język C# oraz strukturą blokową do obsługi sytuacji awaryjnych. Student uczy się pisać kod, który nie przerywa działania przy błędnych danych wejściowych od użytkownika.
Wyobraź sobie, że pracujesz nad prostym kalkulatorem dzielenia dla uczniów szkoły podstawowej. Aplikacja musi pobrać dwie liczby od użytkownika i wyświetlić wynik ich dzielenia. Ponieważ użytkownicy mogą wpisać zamiast liczb dowolny tekst lub próbować dzielić przez zero, Twój program musi być na to w pełni przygotowany. Musisz zastosować blok try-catch z wieloma sekcjami catch, aby osobno obsłużyć błąd formatu (FormatException) oraz błąd matematyczny (DivideByZeroException). Niezależnie od tego, czy obliczenie zakończyło się sukcesem, czy błędem, system musi wyświetlić komunikat o gotowości do kolejnego zadania za pomocą bloku finally. Jest to doskonała okazja do zrozumienia, jak istotna jest segregacja błędów w celu dostarczenia precyzyjnej odpowiedzi użytkownikowi. Program w konsoli powinien działać tak długo, aż użytkownik poda poprawne dane lub zdecyduje się wyjść. Twoim zadaniem jest zapewnienie stabilności aplikacji nawet w ekstremalnych przypadkach. Finalnie wyświetl informację o tym, który konkretnie wyjątek został przechwycony przez system w danej turze obliczeniowej.
Opanowanie pracy z podstawową kolekcją generyczną List<T>. Student uczy się dynamicznej alokacji pamięci na zbiory obiektów oraz poznaje wbudowane metody manipulacji listą, takie jak dodawanie, usuwanie i sortowanie.
Zlecono Ci przygotowanie modułu do zarządzania listą meldunkową w małym pensjonacie. Zamiast sztywnej tablicy, musisz użyć generycznej listy, aby móc swobodnie dodawać nowych gości w trakcie trwania doby hotelowej. Każdy wpis na liście to zwykły ciąg znaków (imię i nazwisko). Twoim zadaniem jest stworzenie prostego menu, które pozwala na : dodanie nowego gościa, usunięcie osoby (jeśli się wymeldowała) oraz wyświetlenie wszystkich aktualnie zameldowanych osób w porządku alfabetycznym. System powinien również umożliwiać szybkie sprawdzenie, czy konkretna osoba znajduje się już w hotelu, korzystając z metody Contains(). Musisz zadbać o to, aby lista nie zawierała pustych wpisów i była zawsze aktualna. To ćwiczenie uczy, dlaczego listy są znacznie wygodniejsze od tablic w sytuacjach, gdy nie znamy z góry liczby rekordów. Program w konsoli powinien działać w interaktywny sposób, reagując na komendy użytkownika. Na koniec dnia menedżer powinien móc wyczyścić całą listę jednym poleceniem Clear(). Finalny raport musi zawierać aktualną liczbę gości (właściwość Count) przed i po sortowaniu.
Zrozumienie działania par klucz-wartość w generycznym słowniku Dictionary<K, V>. Student uczy się projektowania struktur umożliwiających błyskawiczne wyszukiwanie danych bez konieczności przeglądania całego zbioru.
W dużym antykwariacie każda książka posiada unikalny kod kreskowy ISBN, który służy jako klucz do bazy danych. Twoim zadaniem jest stworzenie słownika, który jako klucz przyjmuje ten kod (string), a jako wartość przechowuje pełny tytuł książki. Musisz przygotować system, który pozwala na szybkie dodawanie nowych pozycji oraz natychmiastowe sprawdzanie, jaki tytuł kryje się pod danym kodem. Wyszukiwanie w słowniku jest znacznie wydajniejsze niż w liście, co poczujesz przy próbie odszukania rekordu wśród kilkunastu wpisów. Twoja aplikacja powinna obsługiwać mechanizm sprawdzania czy klucz już istnieje za pomocą metody TryGetValue() lub ContainsKey(), aby uniknąć błędów przy próbie dublowania kodów. Użytkownik w konsoli wpisuje kod, a program odpowiada nazwą książki lub informacją o braku w katalogu. To zadanie uczy, jak dobierać struktury danych do konkretnych problemów inżynierskich – w tym przypadku szybkiego dostępu po unikalnym identyfikatorze. Finalnie program powinien wyświetlić wszystkie kody i tytuły w formie zestawienia tabelarycznego na ekranie. Jest to świetny wstęp do pracy z profesjonalnymi systemami bazodanowymi.
Opanowanie techniki tworzenia i zgłaszania (wyrzucania) własnych klas wyjątków dopasowanych do domeny biznesowej aplikacji. Student uczy się komunikować specyficzne błędy logiczne w sposób ustrukturyzowany.
Budujesz system zabezpieczeń dla firmowego intranetu, który musi weryfikować poprawność haseł i długość loginów. Twoim zadaniem jest stworzenie klasy wyjątku o nazwie "SecurityException", która będzie niosła informację o typie naruszenia zasad bezpieczeństwa. W klasie głównej napisz metodę WeryfikujDostep, która przyjmuje login oraz hasło jako argumenty. Jeśli hasło jest krótsze niż 6 znaków lub login zawiera niedozwolone symbole, metoda powinna rzucić Twój autorski wyjątek za pomocą słowa kluczowego throw. Program w konsoli symuluje proces rejestracji konta, gdzie użytkownik wpisuje dane, a system przekazuje je do weryfikatora wewnątrz bloku try. Jeśli wystąpi naruszenie, blok catch przechwyci Twój konkretny wyjątek i wyświetli na czerwono przyczynę odrzucenia wniosku. To zadanie uczy, jak samodzielnie definiować kontrakty bezpieczeństwa i w elegancki sposób przesyłać informacje o ich złamaniu „w górę” stosu wywołań. Finalny program powinien potwierdzić pomyślne utworzenie konta tylko wtedy, gdy wszystkie testy zakończą się sukcesem. Jest to kluczowy element przy tworzeniu bezpiecznego oprogramowania klasy enterprise.
Poznanie zasady działania kolekcji typu kolejka (FIFO – First In, First Out). Student uczy się modelować procesy, w których kolejność zgłoszeń ma kluczowe znaczenie i dane są pobierane dokładnie w takiej kolejności, w jakiej zostały dodane.
Zaprojektuj system zarządzania ruchem pacjentów w rejestracji medycznej. Musisz wykorzystać kolekcję generyczną Queue<string>, aby zapewnić sprawiedliwą obsługę osób zgłaszających się do lekarza. Program powinien oferować trzy główne funkcje: zarejestrowanie pacjenta na koniec kolejki (Enqueue), wezwanie kolejnej osoby do gabinetu (Dequeue) oraz podejrzenie, kto jest następny bez usunięcia go z listy (Peek). Twoim zadaniem jest obsłużenie sytuacji, gdy lekarz prosi o kolejnego pacjenta, a poczekalnia jest pusta – program nie może się zawiesić, lecz musi wyświetlić stosowny komunikat. Każdy pacjent to po prostu nazwisko przekazywane do systemu w formie tekstowej. Użytkownik w konsoli symuluje poranny dyżur, dodając kilka osób do systemu i stopniowo "obsługując" je przez lekarza. To ćwiczenie świetnie pokazuje, jak proste struktury danych mogą zarządzać skomplikowanymi procesami społecznymi. Finalnie system powinien wyświetlić, ilu pacjentów pozostało jeszcze w kolejce na koniec zmiany. Jest to klasyczny przykład zastosowania buforów danych w informatyce.
Pierwszy kontakt z technologią Language Integrated Query (LINQ). Student uczy się pisać skompaktowane zapytania do kolekcji generycznych, zastępując rozbudowane pętle for eleganckimi wywołaniami metod deklaratywnych.
Otrzymałeś plik z danymi o pracownikach dużej firmy handlowej (pola: Imię, Nazwisko, Pensja, Miasto). Twoim zadaniem jest wczytanie tych informacji do listy generycznej, a następnie przeprowadzenie serii analiz statystycznych przy użyciu LINQ. Musisz w jednej linii kodu odnaleźć wszystkich pracowników, którzy zarabiają powyżej średniej krajowej i mieszkają w Krakowie. Kolejnym Twoim celem jest wyliczenie sumy wszystkich wynagrodzeń w firmie za pomocą metody Sum() oraz znalezienie osoby o najkrótszym nazwisku. Zamiast pisać wielopoziomowe pętle z warunkami if, wykorzystaj metody rozszerzające takie jak Where(), OrderBy(), oraz Select(). Program ma wyświetlić wynikowe listy w czytelny sposób, sortując pracowników alfabetycznie według nazwiska. To zadanie otwiera drzwi do nowoczesnej obróbki danych w .NET, która jest standardem w pracy z bazami danych Entity Framework. Finalnie zaprezentuj raport płacowy, który automatycznie aktualizuje się po dodaniu nowego pracownika do listy bazowej. Wykaż w sprawozdaniu, o ile mniej linii kodu wymaga LINQ w porównaniu do tradycyjnych metod wyszukiwania danych.