C# 6.0 Księga przepisów

Wielkość: px
Rozpocząć pokaz od strony:

Download "C# 6.0 Księga przepisów"

Transkrypt

1 C# 6.0 Księga przepisów Jay Hilyard & Stephen Teilhet przekład: Krzysztof Kapustka, Joanna Zatorska APN Promise Warszawa 2015

2 C# 6.0. Księga przepisów 2015 APN PROMISE SA Authorized translation of English edition of C# 6.0 Cookbook ISBN Copyright 2015 Jay Hilyard, Stephen Teilhet. All rights reserved. This translation is published and sold by permission of O Reilly Media, Inc., which owns or controls of all rights to publish and sell the same. APN PROMISE SA, biuro: ul. Kryniczna 2, Warszawa tel , fax mspress@promise.pl Wszystkie prawa zastrzeżone. Żadna część niniejszej książki nie może być powielana ani rozpowszechniana w jakiejkolwiek formie i w jakikolwiek sposób (elektroniczny, mechaniczny), włącznie z fotokopiowaniem, nagrywaniem na taśmy lub przy użyciu innych systemów bez pisemnej zgody wydawcy. Logo O Reilly jest zarejestrowanym znakiem towarowym O Reilly Media, Inc. Fluent Python, ilustracja z okładki i powiązane elementy są znakami towarowymi O Reilly Media, Inc. Wszystkie inne nazwy handlowe i towarowe występujące w niniejszej publikacji mogą być znakami towarowymi zastrzeżonymi lub nazwami zastrzeżonymi odpowiednich firm odnośnych właścicieli. Przykłady firm, produktów, osób i wydarzeń opisane w niniejszej książce są fikcyjne i nie odnoszą się do żadnych konkretnych firm, produktów, osób i wydarzeń. Ewentualne podobieństwo do jakiejkolwiek rzeczywistej firmy, organizacji, produktu, nazwy domeny, adresu poczty elektronicznej, logo, osoby, miejsca lub zdarzenia jest przypadkowe i niezamierzone. APN PROMISE SA dołożyła wszelkich starań, aby zapewnić najwyższą jakość tej publikacji. Jednakże nikomu nie udziela się rękojmi ani gwarancji. APN PROMISE SA nie jest w żadnym wypadku odpowiedzialna za jakiekolwiek szkody będące następstwem korzystania z informacji zawartych w niniejszej publikacji, nawet jeśli APN PROMISE została powiadomiona o możliwości wystąpienia szkód. ISBN: Projekt okładki: Ellie Volkhausen Ilustracje: Rebecca Demarest Przekład: Krzysztof Kapustka, Joanna Zatorska Redakcja: Marek Włodarz Korekta: Ewa Swędrowska Skład i łamanie: MAWart Marek Włodarz

3 Dla Seth, Toma, Katie i Jenny. Dzięki za waszą przyjaźń. Moje życie jest bogatsze, szczęśliwsze i wypełnione radością dzięki waszej bliskości. Jay Hilyard Dla mego przyjaciela, pastora i nauczyciela Damona Thomasa. Ty i Twoja rodzina jesteście wielkim błogosławieństwem dla naszej. Stephen Teilhet

4

5 Spis treści Wstęp xi 1 Klasy i typy generyczne Wprowadzenie Tworzenie unii Umożliwianie sortowania typu Umożliwianie przeszukiwania typu Zwracanie z metody wielu elementów Parsowanie parametrów wiersza poleceń Inicjowanie stałego pola w czasie wykonywania Tworzenie klonowalnych klas Zapewnianie prawidłowego usuwania obiektu Kiedy i gdzie stosować typy generyczne Wprowadzenie do typów generycznych Odwracanie zawartości posortowanej listy Ograniczanie argumentów typu Inicjowanie zmiennych generycznych do ich domyślnych wartości Dodawanie punktów zaczepienia do wygenerowanych obiektów Kontrolowanie wywołań delegatów wewnątrz delegatu zbiorowego Domknięcia w C# Wykonywanie operacji na listach za pomocą funktorów Kontrolowanie inicjalizacji pól struktury Bardziej przystępne sprawdzanie wartości null Kolekcje, enumeratory i iteratory Wprowadzenie Wyszukiwanie zduplikowanych elementów na liście List<T> Utrzymywanie listy List<T> w posortowanej postaci Sortowanie kluczy i/lub wartości słownika Tworzenie słownika z wartościami granicznymi Utrwalanie kolekcji pomiędzy sesjami aplikacji Testowanie elementów tablicy lub listy List<T> Tworzenie niestandardowych enumeratorów Korzystanie z iteratorów i bloków finally Implementowanie w klasie zagnieżdżonych pętli foreach Korzystanie z bezpiecznego wątkowo słownika dla współbieżnego dostępu bez blokowania v

6 3 Typy danych Wprowadzenie Kodowanie danych binarnych przy użyciu formatu Base Dekodowanie danych binarnych zakodowanych formatem Base Powrotne konwertowanie łańcucha znaków zwróconego z tablicy Byte[] do typu string Przekazywanie łańcucha znaków do metody przyjmującej wyłącznie Byte[] Sprawdzanie, czy łańcuch znakowy jest poprawną liczbą Zaokrąglanie wartości zmiennoprzecinkowej Wybieranie algorytmu zaokrąglania Bezpieczne wykonywanie zawężającego rzutowania numerycznego Testowanie pod kątem poprawności wartości typu wyliczeniowego Wykorzystywanie członków typów wyliczeniowych w masce bitowej Sprawdzanie, czy któraś z flag typu wyliczeniowego została ustawiona Zapytania LINQ i wyrażenia lambda Wprowadzenie Odpytywanie kolejki komunikatów Praca z danymi z wykorzystaniem semantyki zbiorów Ponowne wykorzystywanie sparametryzowanych zapytań LINQ do SQL Sortowanie wyników w zależności od kultury Dodawanie rozszerzeń funkcjonalnych do wykorzystania w LINQ Odpytywanie i łączenie różnych repozytoriów danych Pozyskiwanie danych z plików konfiguracyjnych przy użyciu LINQ Tworzenie kodu XML bezpośrednio z bazy danych Selektywne wybieranie wyników zapytania LINQ i kolekcje niewspierające interfejsu IEnumerable<T> Zaawansowane wyszukiwanie interfejsu Korzystanie z wyrażeń lambda Korzystanie w wyrażeniach lambda z innych modyfikatorów parametrów Przyspieszanie operacji LINQ z użyciem współbieżności Debugowanie i obsługa wyjątków Wprowadzenie Wyłapywanie i ponowne rzucanie wyjątków Obsługa wyjątków rzucanych z metod wywołanych w ramach odbicia Tworzenie nowego typu wyjątku vi Spis treści

7 5.4 Przerywanie na wyjątku pierwszej szansy Obsługiwanie wyjątków rzucanych z asynchronicznego delegatu Dodawanie do wyjątków dodatkowych informacji z użyciem właściwości Exception.Data Praca z nieobsłużonymi wyjątkami w aplikacjach WinForms Praca z nieobsłużonymi wyjątkami w aplikacjach WPF Ustalanie, czy proces przestał odpowiadać Korzystanie w aplikacji z dzienników zdarzeń Monitorowanie dziennika zdarzeń pod kątem konkretnego wpisu Implementowanie prostego licznika wydajności Tworzenie niestandardowych wyświetlaczy debugowania dla naszych klas Wykrywanie miejsca powstania wyjątku Obsługa wyjątków w scenariuszach asynchronicznych Selektywne przetwarzanie wyjątków Odbicie i programowanie dynamiczne Wprowadzenie Listowanie wykorzystywanych zestawów Określanie charakterystyki typów w zestawach Określanie charakterystyki dziedziczenia Wywoływanie członków z użyciem odbicia Pozyskiwanie informacji ze zmiennej lokalnej Tworzenie typu generycznego Różnica pomiędzy dynamic a object Dynamiczne tworzenie obiektów Modyfikowanie obiektów pod kątem rozszerzalności Wyrażenia regularne Wprowadzenie Wyodrębnianie grup z obiektu MatchCollection Weryfikowanie składni wyrażeń regularnych Rozszerzanie podstawowej funkcji zamiany tekstu Implementowanie lepszego tokenizatora Zwracanie pełnego wiersza, w którym znaleziono dopasowanie Wyszukiwanie określonych wystąpień dopasowania Korzystanie z powszechnych wzorców Operacje wejścia-wyjścia w systemie plików Wprowadzenie Wyszukiwanie katalogów lub plików za pomocą znaków wieloznacznych Spis treści vii

8 8.2 Uzyskiwanie drzewa katalogów Parsowanie ścieżki Uruchamianie i używanie narzędzi konsoli Blokowanie fragmentów pliku Oczekiwanie na wystąpienie akcji w systemie plików Porównywanie informacji o wersji dwóch modułów wykonywalnych Wyszukiwanie informacji o wszystkich nośnikach dostępnych w systemie Kompresja i dekompresja plików Zagadnienia sieciowe Wprowadzenie Obsługa błędów serwera Komunikacja z serwerem Przekazywanie żądań przez proxy Pobieranie HTML na podstawie adresu URL Używanie kontrolki przeglądarki internetowej Prekompilacja strony ASP.NET z poziomu programu Stosowanie sekwencji specjalnych i ich usuwanie z danych dla sieci Sprawdzanie niestandardowych stron błędów serwera Tworzenie serwera TCP Tworzenie klienta TCP Symulacja przesłania formularza Przesyłanie danych za pośrednictwem HTTP Komunikacja z wykorzystaniem potoków nazwanych Pingowanie z poziomu kodu Wysyłanie poczty SMTP z wykorzystaniem usługi SMTP Skanowanie portów na komputerze za pomocą gniazd Wykorzystanie bieżących ustawień internetowych Przenoszenie plików za pomocą FTP XML Wprowadzenie Odczyt i dostęp do danych XML w kolejności zdefiniowanej w dokumencie Przeszukiwanie treści dokumentu XML Weryfikacja XML Wykrywanie zmian w dokumencie XML Obsługa niedozwolonych znaków w łańcuchu XML Przekształcanie XML viii Spis treści

9 10.7 Weryfikacja zmodyfikowanych dokumentów XML bez ich ponownego wczytywania Rozszerzanie przekształceń Uzyskiwanie schematów na podstawie istniejących plików XML Przekazywanie parametrów do przekształceń Bezpieczeństwo Wprowadzenie Szyfrowanie i odszyfrowywanie łańcucha Szyfrowanie i odszyfrowywanie pliku Usuwanie informacji dotyczących szyfrowania Zapobieganie uszkodzenia łańcucha podczas transferu danych Gwarantowanie bezpieczeństwa asercji Weryfikacja nadania określonych uprawnień podzespołowi Minimalizowanie obszaru ataków na podzespół Uzyskiwanie informacji na temat zabezpieczeń i inspekcji Nadawanie lub odbieranie dostępu do pliku lub do klucza rejestru Zabezpieczanie danych łańcuchowych Zabezpieczanie danych strumieniowych Szyfrowanie informacji w pliku web.config Uzyskiwanie bezpieczniejszego dojścia do pliku Przechowywanie haseł Wątki, synchronizacja i współbieżność Wprowadzenie Tworzenie pól statycznych dla określonych wątków Zapewnianie bezpiecznego wątkowo dostępu do elementów klasy Zapobieganie dyskretnemu zakończeniu wątku Powiadamianie o zakończeniu działania asynchronicznego delegata Przechowywanie prywatnych danych własnych wątku Nadawanie dostępu do zasobów wielu klientom z wykorzystaniem semafora Synchronizowanie wielu procesów za pomocą muteksu Wykorzystywanie zdarzeń w celu zapewnienia współpracy wątków Wykonywanie operacji niepodzielnych w wątkach Optymalizacja dostępu polegającego głównie na odczycie danych Jak sprawić, by nasze żądania do bazy danych były bardziej skalowalne Uruchamianie zadań w określonej kolejności Przybornik Wprowadzenie Spis treści ix

10 13.1 Obsługa zamykania systemu, zarządzania energią lub zmian w sesji użytkownika Kontrola usługi Pobieranie listy procesów, w których wczytany jest podzespół Używanie kolejek komunikatów na lokalnej stacji roboczej Przechwytywanie wyniku ze standardowego strumienia wyjścia Przechwytywanie standardowego wyjścia procesu Uruchamianie kodu we własnej domenie AppDomain Sprawdzanie wersji systemu operacyjnego i dodatku Service Pack Indeks O autorach x Spis treści

11 Wstęp C# jest językiem przeznaczonym dla programistów wykorzystujących platformę.net firmy Microsoft. Microsoft przestawia C# jako nowoczesny i innowacyjny język służący do tworzenia oprogramowania z wykorzystaniem platformy.net. C# 6.0 kontynuuje tę tradycję dostarczając nowe funkcje ułatwiające programowanie dynamiczne i równoległe. Ponadto pozwala na wykonanie zadań za pomocą mniejszej ilości kodu. C# nadal umożliwia zarówno programowanie deklaratywne, jak i funkcyjne, a zarazem zapewnia świetne wsparcie dla programowania obiektowego. Podsumowując, C# pozwala na pisanie kodu w stylu, który najlepiej pasuje do potrzeb programisty. Zaczęliśmy pisać tę książkę razem, na podstawie problemów, z jakimi zetknęliśmy się podczas nauki C#. Książka rozrosła się wraz z pojawianiem się nowych wyzwań i możliwości języka. W tym wydaniu zmieniliśmy podejście do wielu rozwiązań, uwzględniając najnowsze udoskonalenia C#, takie jak nowy poziom wyrażeń (nameof, interpolacja łańcuchów, operator warunkowy null, inicjalizatory indeksów), deklaracje elementów członkowskich (inicjalizatory auto-właściwości, auto-właściwości służące tylko do pobierania wartości, elementy członkowskie funkcji wewnątrz wyrażeń) oraz funkcje na poziomie instrukcji (filtry wyjątków). Uwzględniliśmy także nowe elementy programowania dynamicznego (C# 4.0) i programowania asynchronicznego (C# 5.0), zarówno w istniejących, jak i w nowych przepisach. Chcieliśmy w ten sposób ułatwić Czytelnikom zrozumienie ich użycia. Mamy nadzieję, że te dodatki pomogą Czytelnikom uporać się z pewnymi powszechnymi (a także z nieco rzadszymi) problemami oraz wątpliwościami, które pojawiają się u każdego, kto rozpoczyna naukę C#, zgłębia tajniki nowych możliwości języka lub pracuje nad zagadnieniami, które wymagają zboczenia z utartych ścieżek podczas pracy. W niektórych przepisach rozwiązujemy problemy, które według nas zostały pominięte w bibliotece.net Framework Class Library (FCL), chociaż Microsoft udostępnił tysiące funkcji, dzięki którym nie musimy na nowo odkrywać Ameryki. Niektóre z tych rozwiązań mogą się nam przydać od razu, a z niektórymi problemami możemy się nigdy nie spotkać, lecz mamy nadzieję, że ta książka pomoże Czytelnikom wykorzystać pełnię możliwości języka C# i platformy.net. Książka została opracowana z myślą o tych typach problemów, które Czytelnik będzie rozwiązywać w ciągu swojej kariery programisty C#. Te rozwiązania są zwane przepisami; każdy przepis dotyczy jednego problemu, prezentuje jego rozwiązanie, zawiera xi

12 jego omówienie wraz z powiązanymi informacjami. Na końcu przepisu znajduje się lista zasobów, dotyczących na przykład lokalizacji w FCL, w której można znaleźć więcej informacji na temat wykorzystywanych klas. Wymienione są też inne książki, dotyczące tego problemu, powiązane artykuły i inne przepisy. Format pytań i odpowiedzi dostarcza kompletnych rozwiązań problemów, zwiększając czytelność i ułatwiając korzystanie z książki. Niemal każdy przepis zawiera kompletny, udokumentowany kod przykładowy, demonstrujący sposób rozwiązania problemu, omówienie działania technologii, a także listę technologii alternatywnych, ograniczeń i innych ważnych czynników. Dla kogo jest ta książka Z tej książki mogą korzystać nie tylko doświadczeni programiści C# lub.net jej przeznaczeniem jest służyć użytkownikom na wszystkich poziomach zaawansowania. Ta książka zawiera rozwiązania problemów, z którymi programiści stykają się na co dzień, a także niektórych rzadziej spotykanych problemów. Przepisy są przeznaczone dla programistów, którzy muszą rozwiązać problemy już teraz, a nie dla tych, którzy muszą się najpierw uczyć teorii. Chociaż podręczniki i przewodniki mogą nas nauczyć ogólnych koncepcji, zwykle nie pomogą w rozwiązaniu prawdziwych problemów. My wybraliśmy metodę nauczania na podstawie przykładów, która wykorzystuje naturalny sposób nauki większości osób. Z większością problemów, opisanych w tej książce, programiści C# spotykają się dość często, lecz niektóre bardziej zaawansowane problemy wymagają bardziej skomplikowanych rozwiązań, które wymagają wykorzystania wielu technik. Każdy przepis został opracowany tak, aby umożliwić szybkie zrozumienie problemu, zaprezentować jego rozwiązanie oraz wskazać potencjalne konsekwencje. Dzięki temu Czytelnicy mogą szybko i efektywnie rozwiązać swoje problemy. Aby zaoszczędzić Czytelnikom wysiłku związanego z przepisywaniem rozwiązania, na stronie wydawnictwa, prezentującej tę książkę, udostępniamy przykładowy kod zawarty w tej książce. Proponowany przez nas tryb kopiuj-wklej ułatwi mniej doświadczonym programistom sprawdzenie dobrych praktyk programistycznych w akcji. Pakiet kodu przykładowego zawiera przypadek testowy, który wykorzystuje każde rozwiązanie, lecz w samej książce można znaleźć wystarczająco dużo kodu, by zaimplementować rozwiązania bez kodu przykładowego. Kod przykładowy jest dostępny na stronie tej książki ( Co będzie potrzebne Aby uruchomić przykłady z tej książki, potrzebny jest komputer z systemem operacyjnym Windows w wersji 7 lub późniejszej. Kilka rozwiązań związanych z zagadnieniami sieciowymi i XML wymaga działającego serwera Microsoft Internet Information Server xii Wstęp

13 (IIS) w wersji co najmniej 7.5, a przykłady dotyczące FTP w rozdziale 9 wymagają lokalnie skonfigurowanego serwera FTP. Aby otworzyć i skompilować przykłady z tej książki, potrzebny jest program Visual Studio Jeśli Czytelnik jest zaznajomiony z narzędziem Framework SDK oraz z jego kompilatorem wiersza poleceń, nie powinien mieć żadnych trudności ze śledzeniem tekstu tej książki oraz uruchomieniem przykładowego kodu. Uwagi dotyczące plaformy Rozwiązania przedstawione w tej książce zostały utworzone z wykorzystaniem programu Visual Studio Różnice między C# 6.0 i C# 3.0 są znaczące, co zostało odzwierciedlone w uaktualnionym kodzie przykładowym. Warto wspomnieć, że chociaż obecna jest już wersja 6.0 języka, to najnowsze wydanie platformy.net ma numer wersji 4.6. Język C# nadal podlega udoskonaleniu wraz z każdą nową wersją platformy.net, a wersja C# 6.0 oferuje wiele możliwości, które pozwalają na tworzenie programów w dowolnym stylu, który najlepiej odpowiada bieżącemu zadaniu. Organizacja książki Ta książka zawiera 13 rozdziałów. Każdy z nich skupia się na konkretnym zagadnieniu, dla którego przedstawione są rozwiązania w języku C#. Poniżej przedstawiamy podsumowanie każdego rozdziału, aby Czytelnik poznał ogólny zarys treści tej książki: Rozdział 1, Klasy i typy generyczne Ten obszerny rozdział zawiera przepisy dotyczące klas i struktur danych, a także typów generycznych, które pozwalają na przetwarzanie wartości różnych typów w jednakowy sposób. Przepisy znajdujące się w tym rozdziale dotyczą szerokiej tematyki, począwszy od typów zamkniętych przez przekształcanie klas do pełnego systemu przetwarzania argumentów z wiersza poleceń, aż po zagadnienia projektowania klas. Znajdziemy tu przepisy, które w ogólny sposób ułatwiają zrozumienie typów generycznych, a także przepisy prezentujące sytuacje, w których te typy sprawdzają się najlepiej, prezentujące wsparcie, jakie oferuje dla nich platforma.net, a także pokazujące, jak można utworzyć własne implementacje kolekcji. Rozdział 2, Kolekcje, enumeratory i iteratory Ten rozdział zawiera przepisy wykorzystujące kolekcje, enumeratory i iteratory. Przepisy dotyczące kolekcji wykorzystują a także rozszerzają ich funkcje tablice (jedno i wielowymiarowe, jak również tablice nieregularne), klasę List<T> i wiele innych klas kolekcji. Omówione są także kolekcje generyczne oraz różne sposoby tworzenia własnych, silnie typowanych kolekcji. Opisujemy tworzenie własnych enumeratorów, pokazujemy, jak można zaimplementować iteratory typów generycznych Uwagi dotyczące plaformy xiii

14 i niegenerycznych, a także jak używać iteratorów w implementacji pętli foreach. Opisujemy też niestandardowe implementacje iteratorów. Rozdział 3, Typy danych Ten rozdział dotyczy łańcuchów, liczb i typów wyliczeniowych. Zebrane w nim przepisy prezentują kodowanie i dekodowanie łańcuchów, przekształcenia liczbowe, a także sprawdzanie, czy łańcuchy zawierają wartość liczbową. W rozdziale tym zajmujemy się też wyświetlaniem, przekształcaniem i testowaniem typów wyliczeniowych oraz wykorzystaniem wyliczeń zawierających flagi bitowe. Rozdział 4, Zapytania LINQ i wyrażenia lambda Ten rozdział dotyczy wykorzystania technologii Language Integrated Query (LINQ), włącznie z przykładem równoległej wersji LINQ (PLINQ). Rozdział ten zawiera przepisy wykorzystujące wiele standardowych operatorów zapytań oraz pokazujące sposób użycia niektórych operatorów zapytań, które choć nie są słowami kluczowymi języka, to jednak są dość potężne. Omówione są też wyrażenia lambda, a prezentujące je przepisy wykorzystują je zamiast starego typu delegatów. Rozdział 5, Debugowanie i obsługa wyjątków Ten rozdział dotyczy debugowania i obsługi wyjątków. Prezentujemy przepisy, które wykorzystują typy danych, dostępne w przestrzeni nazw System.Diagnostics, czyli logi zdarzeń, liczniki wydajności i niestandardowe widoki debugera dla naszych typów. Skupiamy się też na najlepszych sposobach implementacji obsługi wyjątków w aplikacji. Znajdziemy tu także przepisy pokazujące, jak zapobiegać wystąpieniu nieobsłużonych wyjątków. Wreszcie, przygotowaliśmy też przepisy prezentujące sposoby radzenia sobie z różnymi trudnymi sytuacjami, takimi jak wyjątki z metod z późnym wiązaniem oraz asynchroniczna obsługa wyjątków. Rozdział 6, Odbicie i programowanie dynamiczne Ten rozdział prezentuje użycie wbudowanego systemu inspekcji zestawów, dostępnego w platformie.net, w celu określenia typów, interfejsów i metod zaimplementowanych w zestawie. Pokazujemy też, jak uzyskać do nich dostęp z wykorzystaniem mechanizmu późnego wiązania. Prezentujemy również dynamiczny styl programowania z użyciem dynamic, ExpandoObject i DynamicObject. Rozdział 7, Wyrażenia regularne Ten rozdział opisuje przydatny zestaw klas, służących do sprawdzania dopasowania łańcuchów do wyrażeń regularnych. W przepisach iterujemy po wynikach dopasowania wyrażeń regularnych, dzielimy łańcuchy na tokeny, wyszukujemy i zastępujemy znaki, a także weryfikujemy składnię wyrażeń regularnych. Uwzględniliśmy też przepis zawierający najpopularniejsze wzorce wyrażeń regularnych. Rozdział 8, Operacje wejścia-wyjścia w systemie plików Ten rozdział opisuje interakcje z systemem plików na trzy różne sposoby: pierwszy dotyczy typowych interakcji z plikiem; drugi dotyczy interakcji opartych xiv Wstęp

15 na katalogach czy folderach; a trzeci dotyczy zaawansowanych zagadnień operacji wejścia-wyjścia w systemie plików. Rozdział 9, Zagadnienia sieciowe Ten rozdział omawia oferowane przez platformę.net opcje łączności oraz dostępu do zasobów sieciowych i treści WWW z poziomu kodu. Przepisy dotyczą bezpośredniego wykorzystania protokołu TCP/IP, wykorzystywania potoków nazwanych na potrzeby komunikacji, tworzenia własnego skanera portów, określania konfiguracji strony WWW z poziomu kodu i wielu innych zagadnień. Rozdział 10, XML Jeśli korzystamy z platformy.net, prawdopodobnie kiedyś zetkniemy się z formatem XML. W tym rozdziale omawiamy pewne przypadki użycia XML, a także pokazujemy, jak obsługiwać ten format programowo za pomocą techniki LINQ to XML, obiektu XmlReader/XmlWriter i XmlDocument. Rozdział ten zawiera przykłady wykorzystujące zarówno XPath, jak i XSLT, a także obejmuje zagadnienia weryfikacji XML i przekształceń formatu XML w HTML. Rozdział 11, Bezpieczeństwo Istnieje wiele metod pisania niebezpiecznego kodu, a tylko kilka sposobów tworzenia bezpiecznego kodu. W tym rozdziale omawiamy zagadnienia, takie jak kontrolowanie dostępu do typów, szyfrowanie i odszyfrowywanie, bezpieczne przechowywanie danych, a także stosowanie zabezpieczeń programistycznych i deklaratywnych. Rozdział 12, Wątki, synchronizacja i współbieżność Ten rozdział dotyczy zagadnienia wykorzystania wielu wątków w programie.net, a także implementowania wątków w aplikacji, ochrony zasobów oraz zapewnienia bezpiecznego dostępu współbieżnego, przechowywania danych wątków, uruchamianie zadań w kolejności oraz używania podstawowych elementów synchronizacji platformy.net w celu pisania kodu bezpiecznego wątkowo. Rozdział 13, Przybornik W tym rozdziale zawarte są przepisy dotyczące różnorodnych operacji, często wykonywanych przez programistów, takich jak określanie lokalizacji zasobów systemowych, wysyłania wiadomości oraz pracy z usługami. W rozdziale tym uwzględniono też rzadziej używane, lecz przydatne elementy aplikacji, takie jak kolejki komunikatów, uruchamianie kodu w osobnej domenie AppDomain i określanie wersji podzespołów w Global Assembly Cache (GAC). Niektóre przepisy są powiązane; w tej sytuacji w puncie Zobacz także, a czasem także w tekście punktu Omówienie znajdziemy odpowiednie odniesienie do innego przepisu. Organizacja książki xv

16 Co zostało pominięte Ta książka nie jest podręcznikiem ani elementarzem języka C#. Do godnych polecenia przewodników po języku oraz podręczników, które zostały wydane przez O Reilly, należą: C# 6.0 in a Nutshell autorstwa Josepha Albahari i Bena Albahari; C# 6.0 Pocket Reference, także autorstwa Josepha Albahari i Bena Albahari; oraz Concurrency in C# Cookbook autorstwa Stephena Cleary. Nieoceniona jest także biblioteka MSDN. Znajdziemy ją w pakiecie Visual Studio 2015, a także online pod adresem Konwencje stosowane w tej książce Ta książka wykorzystuje następujące konwencje typograficzne: Kursywa Stosowana w adresach URL, nazwach katalogów i plików, w nazwach opcji, a także czasami w celu wyróżnienia. Krój o stałej szerokości Stosowany w listingach oraz do wyróżnienia elementów kodu, takich jak polecenia, opcje, przełączników, zmiennych, atrybutów, kluczy, funkcji, typów, klas, przestrzeni nazw, metod, właściwości, parametrów, wartości, obiektów, zdarzeń, procedur obsługi zdarzeń, znaczników XML, znaczników HTML, makr, treści plików i wyniku poleceń. Pogrubiony krój o stałej szerokości Wykorzystywany w listingach w celu podkreślenia ważnego fragmentu kodu. Krój o stałej szerokości z kursywą Wykorzystywany do oznaczenia części kodu, które należy zastąpić. //... Wielokropki w kodzie C# reprezentują tekst pominięty w celu większej przejrzystości. <! > Wielokropki w schematach XML i kodzie dokumentów oznaczają tekst pominięty w celu większej przejrzystości. Ta ikona oznacza wskazówkę, sugestię lub ogólną uwagę. xvi Wstęp

17 Ta ikona oznacza ostrzeżenie lub przestrogę. Kilka słów na temat kodu Prawie każdy przepis znajdujący się w tej książce zawiera jeden lub kilka przykładów kodu. Te przykłady są zawarte w poszczególnych rozwiązaniach i mają postać fragmentów kodu oraz całych projektów, które można natychmiast wykorzystać we własnej aplikacji. Większość przykładowego kodu została umieszczona w klasie lub strukturze, co ułatwia jego wykorzystanie we własnej aplikacji. Ponadto, uwzględnione zostały także dyrektywy using dla każdego przepisu, dzięki czemu Czytelnik nie musi szukać modułów, które należy dołączyć do kodu. Pełna obsługa błędów została uwzględniona tylko w krytycznych miejscach, takich jak parametry wejściowe. Dzięki temu możemy z łatwością rozpoznać poprawne i niepoprawne dane wejściowe. W wielu przepisach pominięto obsługę błędów. To ułatwia zrozumienie rozwiązania, ponieważ Czytelnik może się skupić na kluczowych koncepcjach. Korzystanie z przykładowego kodu Przykładowy kod z tej książki można znaleźć pod adresem: Celem tej książki jest pomoc w wykonaniu różnych zadań. Ogólnie rzecz biorąc, kod zawarty w tej książce można wykorzystać w swoich programach i dokumentacji. Czytelnik nie musi się z nami kontaktować w celu uzyskania zezwolenia, chyba że zamierza odtworzyć znaczną część kodu. Na przykład, napisanie programu, który wykorzystuje kilka fragmentów kodu z tej książki, nie wymaga zezwolenia. Sprzedaż lub dystrybucja płyty CD-ROM zawierającej przykłady z książek wydawnictwa O Reilly wymaga zezwolenia. Odpowiedź na pytanie, zawierająca cytat z tej książki wraz z kodem przykładowym nie wymaga zezwolenia. Włączenie znacznej części przykładowego kodu z tej książki do dokumentacji produktu nie wymaga zezwolenia. Doceniamy, lecz nie wymagamy not wskazujących pochodzenie kodu. Mamy tu na myśli tytuł, autora, wydawcę i numer ISBN książki. Na przykład: C# 6.0 Księga przepisów, wydanie 4., autorstwa Jay a Hilyarda i Stephena Teilheta. Copyright 2015 Jay Hilyard i Stephen Teilhet, Jeśli Czytelnik uważa, że wykorzystanie przez niego przykładowego kodu wykracza poza opisane tu przypadki dopuszczalnego użycia, zapraszamy do kontaktu pod adresem permissions@oreilly.com. Kilka słów na temat kodu xvii

18 Podziękowania Praca nad tą książką zaczęła się dla nas, gdy zaczęliśmy się zapoznawać z językiem C#. Kontynuowaliśmy ją przez lata, wykorzystując język na wiele nowych i ekscytujących sposobów. Ponieważ od ostatniego wydania książki pojawiły się nie tylko nowe funkcje z wersji C# 6.0, ale także z wersji C# 4.0 i C# 5.0, zdecydowaliśmy się, że nadszedł czas, aby przejrzeć trzy pierwsze wydania i sprawdzić, jak można udoskonalić istniejące przepisy oraz poznać lepsze sposoby wykonania zadań programistycznych w C#. Wraz ze zdobywaniem coraz obszerniejszej wiedzy na temat języka C# i platformy.net, pracowaliśmy ciężko nad tym wydaniem, aby przybliżyć Czytelnikom rozwój języka C# i pokazać, jak lepiej wykonywać swoją pracę. Nie napisalibyśmy tej książki bez wsparcia wymienionych dalej osób, dlatego chcielibyśmy podziękować im za ich wysiłki. Nasze uznanie należy się Brianowi MacDonaldowi (naszemu wydawcy), Heather Scherer, Rachel Monaghan, Nickowi Adamsowi i Sarze Peyton, którzy pilnowali terminów i wykonali kawał dobrej roboty, aby ta książka została ukończona i znalazła się na półkach księgarskich. Dziękujemy za Wasze wysiłki. Chcemy też wyrazić wdzięczność zespołowi naszych recenzentów technicznych, składającemu się ze Stevena Munyana, Lee Cowarda i Nicka Pinkhama. Doceniamy cały czas spędzony na pomaganiu nam w ulepszaniu tej książki, a także dogłębne komentarze. Ta książka nie powstałaby bez Waszych cennych uwag i oboje Wam za to dziękujemy. Od Jay a Hilyarda Dziękuję Steve owi Teilhetowi za jego pomysły, poczucie humoru i chęć ponownego przyłączenia się do tej przygody. Praca z Tobą zawsze sprawiała mi radość, nawet jeśli zwykle odbywała się nocami i podczas weekendów, i niemal zawsze wirtualnie. Chciałbym podziękować mojej żonie Brooke. Chociaż wiedziałaś, że będę musiał poświęcić czas przeznaczony dla rodziny, byłaś dla mnie wielkim wsparciem, służyłaś zachętą i pomocą. Jak zwykle, nie byłoby to możliwe bez Twojej pomocy. Dziękuję i kocham Cię! Dziękuję moim synom, Owenowi i Drewowi. Ciągle zaskakuje mnie to, że potrafią sprawić, bym spojrzał na problem pod innym kątem. Czuję się dumny z Waszych osiągnięć. To, że oboje interesujecie się tą samą dziedziną, którą się zajmuję, bardzo mnie cieszy. Nie mógłbym sobie wymarzyć lepszych synów. Dziękuję Philowi i Gailowi za ich wsparcie i zrozumienie, które mi okazywali, gdy musiałem pracować podczas wakacji, a także za obecność i gotowość do pomocy, jakiej mogą udzielić tylko dziadkowie. Dziękuję też mojej Mamie za miesięczną dawkę rozsądku. Dziękuję grupie dobrych przyjaciół: Sethowi i Katie Fiermonti, Tomowi Bebbingtonowi i Jennie Roberts. Dzięki przyjaciołom wszystko staje się lepsze, szczególnie jeśli towarzyszy temu dobre piwo. xviii Wstęp

19 Dziękuję Scottowi Cronshawowi, Billowi Bolevicowi, Melissie Jurkoic, Mike owi Kennie owi, Alexowi Shore owi, Dave owi Flandersowi, Aaronowi Reddishowi, Rakshitowi Jain, Jasonowi Phelpsowi, Joshowi Clairmontowi, Bobowi Blaisowi, Kim Serpie, Stu Savage owi, Gaurangowi Patelowi, Jesse owi Petersowi, Kenowi Jonesowi, Maheshowi Unnikrishnanowi, T Antoniowi, Mary Ellen Sawyer, Jonowi Godboutowi, Atulowi Kaulowi, Markowi Millerowi, Richowi Labenskiemu, Lance owi Simpsonowi, Timowi Beaulieu i Lee Horganowi za stworzenie wspaniałego zespołu osób, z którymi mogłem współpracować. Każdy z Was pracuje niesłychanie ciężko i doceniam wszystko, co robicie. Wreszcie, chciałbym ponownie podziękować mojej rodzinie i przyjaciołom za pytania o książkę, której nie rozumieli i za ich ekscytację tym przedsięwzięciem. Od Steve a Teilheta Jestem dumny z tego, że mogę liczyć na Jay a Hilyarda, jak na dobrego przyjaciela, wspaniałego współpracownika i ciężko pracującego współautora. Nie codziennie spotyka się osobę, która będzie nie tylko zaufanym przyjacielem, ale z którą będzie się tak świetnie pracować. Dziękuję za kolejną udaną książkę. Moja żona Kandis Teilhet towarzyszyła mi na każdym kroku tej drogi, dając mi siłę do wytrwania i ukończenia tej pracy. Mojej miłości do Ciebie nie zdołają wyrazić żadne słowa. Moi dwaj synowie Patrick i Nicholas Teilhet wygładzali moje ścieżki. Nie mógłbym sobie wymarzyć lepszych synów. Teraz, gdy wkraczacie w kolejny etap życia, jestem podekscytowany tym, co zdołacie osiągnąć; może też napiszecie książkę. Dziękuję mojej mamie, tacie i bratu, którzy byli zawsze gotowi, aby mnie wysłuchać i wesprzeć. Wreszcie, chciałbym podziękować zespołowi IBM, w którego skład wchodzili Larry Rose, Babita Sharma, Jessica Berliner, Jeff Turnham, John Peyton, Kris Duer, Robert Stanzel, Shu Wang, Bingzhou Zheng, Dave Steinberg, Dave Stewart, Jason Todd, Alexei Pivkine, Joshua Clark, William Frontiero, Matthew Murphy, Omer Trip, Marco Pistoia, Enrique Varillas, Guillermo Hurtado, Bao Lu, Mary Santo, Diane Redfearn, Urmi Chatterjee, Joshua Ho, Kenneth Cheung, Andrew Mak, Daniel Nguyen, Jennifer Calder, Tahseen Shabab, Srinivas Sripada, David Marshak, Larry Gerard, Douglas Wilson, Steve Hikida i wielu innych. Wasza ciężka praca i zdolności są inspirujące. Podziękowania xix

20

21 Rozdział 1 Klasy i typy generyczne 1.0 Wprowadzenie Zawarte w niniejszym rozdziale przepisy dotyczą podstaw języka C#. Tematy obejmują klasy i struktury, sposób ich wykorzystywania i różnice między nimi, a także powody stosowania jednego typu danych zamiast drugiego. Bazując na tej wiedzy będziemy konstruować klasy z funkcjonalnością odziedziczoną, czyli przykładowo takie, które mogą być sortowane, przeszukiwane, usuwane i klonowane. Dodatkowo zagłębimy się w tematyce unii, inicjalizacji pól, wyrażeń lambda, metod częściowych, delegatów pojedynczych i zbiorowych, domknięć, funktorów oraz kilku innych rzeczy. Rozdział ten zawiera również przepis dotyczący procesu parsowania parametrów wiersza poleceń, co jest jednym z najbardziej lubianych tematów. Zanim jednak zagłębimy się w konkretne przepisy, powtórzymy sobie pewne kluczowe informacje w zakresie możliwości klas, struktur i typów generycznych, jakie wynikają z paradygmatu programowania zorientowanego obiektowo. Klasy są znacznie bardziej elastyczne od struktur. Struktury również mogą implementować interfejsy, ale w przeciwieństwie do klas nie mogą dziedziczyć po innych klasach lub strukturach. Ograniczenie to uniemożliwia nam tworzenie hierarchii struktur, co z powodzeniem możemy osiągnąć przy użyciu klas. Implementowany w ramach abstrakcyjnej klasy bazowej polimorfizm w przypadku struktur również jest niedopuszczalny, jako że struktura nie może dziedziczyć po innej klasie, z wyjątkiem konwersji boxing do typu Object, ValueType lub Enum. Struktury, podobnie jak każdy inny typ wartości, dziedziczą niejawnie z klasy System. ValueType. Na pierwszy rzut oka struktura podobna jest do klasy, lecz w rzeczywistości znacznie się od niej różni. Wiedza na temat tego, kiedy należy używać struktury, a kiedy klasy w dużym stopniu ułatwi nam projektowanie aplikacji. Niepoprawne korzystanie ze struktur może skutkować niewydajnym, a przy tym trudnym do zmodyfikowania kodem. Struktury mają nad typami referencyjnymi pewną przewagę wydajnościową. Jeśli struktura została przydzielona na stosie (a więc nie jest przechowywana w obrębie typu referencyjnego), dostęp do struktury i jej danych będzie nieco szybszy niż w przypadku 1

22 typu referencyjnego na stercie. By dostać się do własnych danych, obiekty typu referencyjnego muszą sięgać na stertę z użyciem referencji. Druga i jednocześnie dużo większa zaleta struktur odnosi się do czyszczenia pamięci. Proces czyszczenia przydzielonej na stosie pamięci struktury sprowadza się jedynie do prostej zmiany adresu wskazywanego przez wskaźnik stosu, co odbywa się przy powrocie z wywołania metody. Wywołanie to jest dużo szybsze w porównaniu z mechanizmem odzyskiwania pamięci, który automatycznie sprząta za nas typy referencyjne z zarządzanej sterty. Jako że proces sprzątania jest nieco odroczony w czasie, związany z nim koszt nie jest od razu zauważalny. Gdy zachodzi potrzeba przekazania struktur do metod przez wartość, ich wydajność w porównaniu z wydajnością klas wypada zwyczajnie słabo. Ponieważ struktury przechowywane są na stosie, w momencie przekazania ich do metody przez wartość struktury wraz z zawartymi w nich danymi muszą zostać skopiowane do nowej zmiennej lokalnej (do parametru metody, który posłuży do odebrania struktury). Kopiowanie struktury trwa znacznie dłużej niż przekazanie do metody pojedynczej referencji do obiektu, chyba że rozmiar struktury jest taki sam lub mniejszy niż rozmiar wskaźnika na danej maszynie. Tym samym koszt skopiowania na maszynie 32-bitowej struktury o rozmiarze 32 bitów będzie tak samo niski, jak przekazanie jej przez referencję (która ma rozmiar wskaźnika). Pamiętajmy o tym, gdy następnym razem będziemy wybierać pomiędzy klasą a strukturą. O ile tworzenie, uzyskiwanie dostępu lub usuwanie obiektów klas może trwać dłużej, o tyle możemy dużo stracić na wydajności, gdy zachodzi potrzeba wielokrotnego przekazania struktury przez wartość do jednej lub wielu metod. Utrzymywanie rozmiarów struktur na niskim poziomie minimalizuje straty wydajności, jakie ponosimy przekazując je przez wartość. Klasy używamy, gdy: Jej tożsamość jest istotna. Struktury kopiowane są niejawnie w momencie przekazania ich do metody przez wartość. Będzie ona zajmować dużą ilość pamięci. Jej pola wymagają inicjalizatorów. Musimy odziedziczyć coś z klasy bazowej. Potrzebujemy polimorficznego zachowania, tj. musimy zaimplementować abstrakcyjną klasę bazową, z której następnie utworzymy kilka podobnych i dziedziczących po niej klas (zwróćmy uwagę, że polimorfizm można również zaimplementować przy użyciu interfejsów, ale nie zaleca się stosowania interfejsu w przypadku typu wartości, bo gdy struktura zostanie skonwertowana do typu interfejsu, wówczas konwersja boxing spowoduje spadek wydajności). Struktury używamy, gdy: Będzie się ona zachowywać niczym typ prymitywny (int, long, byte, itd.). Musi zajmować niewielką ilość pamięci. 2 Rozdział 1: Klasy i typy generyczne

23 Wywołujemy metodę P/Invoke, która wymaga przekazania struktury przez wartość. Platform Invoke, lub w skrócie P/Invoke, umożliwia odwołanie się z poziomu kodu zarządzanego do metody niezarządzanej, wyeksponowanej w ramach biblioteki DLL. W wielu przypadkach niezarządzana metoda biblioteki DLL wymaga przekazania do niej struktury przez wartość. Skorzystanie ze struktury będzie w tym przypadku nie tylko bardziej wydajne, ale będzie w takim wypadku jedynym możliwym sposobem dokonania tego. Chcemy zredukować wpływ modułu odzyskiwania pamięci na wydajność aplikacji. Jej pola będą inicjowane wyłącznie do ich wartości domyślnych. Wartością domyślną dla typów numerycznych będzie 0, dla typów Boolean false, a dla typów referencyjnych null. W wersji 6.0 języka C# struktury mogą mieć domyślny konstruktor, który może posłużyć do inicjalizacji pól struktury do wartości niestandardowych. Nie musimy niczego dziedziczyć po klasie bazowej (poza klasą ValueType, po której dziedziczą wszystkie struktury). Nie potrzebujemy polimorficznego zachowania. W przypadku przekazywania struktur do metod oczekujących obiektów, co ma miejsce chociażby w przypadku niegenerycznych kolekcji w bibliotece Framework Class Library (FCL), struktury mogą obniżyć wydajność aplikacji. Przekazanie struktury (lub też jakiegokolwiek innego typu prostego) do metody wymagającej obiektu skutkować będzie konwersją boxing tej struktury. Boxing odnosi się do procesu opakowywania typu wartości w określony obiekt. Operacja ta jest czasochłonna i może negatywnie wpływać na wydajność. Dodajmy jeszcze, że typy generyczne pozwalają nam pisać bezpieczny i wydajny kod oparty na kolekcjach i wzorcach. Typy generyczne dają nam sporo dodatkowych możliwości, ale wraz z nimi pojawia się konieczność ich prawidłowego stosowania. Jeśli rozważamy zamianę naszych obiektów ArrayList, Queue, Stack i Hashtable na ich generyczne odpowiedniki, warto zapoznać się z przepisami 1.9 i Dowiemy się z nich przykładowo, że konwersja taka nie zawsze jest łatwa oraz że istnieją określone powody, dla których nie powinniśmy jej wcale dokonywać. 1.1 Tworzenie unii Problem Musimy utworzyć typ danych, który zachowywał się będzie podobnie jak unia w języku C++. Unia jest typem danych, który przydaje się głównie w scenariuszach interoperacyjnych, gdzie kod niezarządzany przyjmuje i/lub zwraca unię. Nie zaleca się jej wykorzystywania w innych sytuacjach. 1.1 Tworzenie unii 3

24 Rozwiązanie Skorzystamy ze struktury oznaczonej atrybutem StructLayout (z podanym w konstruktorze rodzajem układu LayoutKind.Explicit). Każde pole w tej strukturze oznaczymy atrybutem FieldOffset. Poniższa struktura definiuje unię, w której będziemy mogli przechować pojedynczą wartość numeryczną ze znakiem: using System.Runtime.InteropServices; [StructLayoutAttribute(LayoutKind.Explicit)] struct SignedNumber [FieldOffsetAttribute(0)] public sbyte Num1; [FieldOffsetAttribute(0)] public short Num2; [FieldOffsetAttribute(0)] public int Num3; [FieldOffsetAttribute(0)] public long Num4; [FieldOffsetAttribute(0)] public float Num5; [FieldOffsetAttribute(0)] public double Num6; Następna struktura podobna jest do struktury SignedNumber, z wyjątkiem tego, że prócz wartości numerycznej ze znakiem może ona dodatkowo przechowywać typ String: [StructLayoutAttribute(LayoutKind.Explicit)] struct SignedNumberWithText [FieldOffsetAttribute(0)] public sbyte Num1; [FieldOffsetAttribute(0)] public short Num2; [FieldOffsetAttribute(0)] public int Num3; [FieldOffsetAttribute(0)] public long Num4; [FieldOffsetAttribute(0)] public float Num5; [FieldOffsetAttribute(0)] public double Num6; [FieldOffsetAttribute(16)] 4 Rozdział 1: Klasy i typy generyczne

25 public string Text1; Omówienie Unie stosuje się zazwyczaj w kodzie C++, jednak z powodzeniem możemy je implementować również w języku C#, posługując się dostępnym w nim typem struktury. Unia jest strukturą danych, która w wyznaczonym dla niej obszarze pamięci przechowuje więcej niż jeden typ danych. Przykładowo struktura SignedNumber jest unią zbudowaną przy wykorzystaniu struktury C#. Struktura ta przyjmuje dowolną wartość numeryczną ze znakiem dowolnego typu (sbyte, int, long, itd.), przy czym przyjmuje je tylko w jednej lokalizacji w ramach struktury. Jako że atrybut StructLayoutAttribute ma zastosowanie zarówno do struktur, jak i do klas, do utworzenia unii możemy również wykorzystać klasę. Zwróćmy uwagę, że do konstruktora atrybutu FieldOffsetAttribute przekazywana jest wartość 0. Oznacza to, że dane pole zostanie przesunięte względem początku struktury o zero bajtów. Atrybut ten wykorzystywany jest w połączeniu z atrybutem StructLayoutAttribute w celu ręcznego określenia początku poszczególnych pól struktury (inaczej mówiąc, przesunięcia względem początku struktury w pamięci, będącego początkiem każdego z jej pól). Atrybut FieldOffsetAttribute możemy stosować wyłącznie z atrybutem StructLayoutAttribute ustawionym na LayoutKind.Explicit. Nie możemy go jednak wykorzystywać dla statycznych członków wewnątrz struktury. Unie mogą być niekiedy problematyczne, jako że w praktyce kilka typów danych jest na siebie nałożonych jeden na drugi. Największym problemem jest tu wyodrębnianie poprawnego typu danych ze struktury. Zastanówmy się, co się stanie, jeśli w strukturze SignedNumber zdecydujemy się przechować wartość numeryczną typu long o nazwie long. MaxValue. Póżniej możemy przez przypadek spróbować wyodrębnić tę wartość w formie typu danych byte. Jeśli to zrobimy, zostanie nam zwrócony jedynie pierwszy bajt wartości typu long. Kolejnym problemem może być rozpoczynanie pól struktury z właściwym przesunięciem. Unia SignedNumberWithText nakłada na siebie kilka wartości numerycznych ze znakiem, z przesunięciem równym zero. Ostatnie pole tej struktury rozpoczyna się z 16-bajtowym przesunięciem od początku pamięci struktury. Jeśli na którykolwiek z typów numerycznych ze znakiem nałożymy przypadkowo pole tekstowe Text1, wówczas w czasie działania programu zostanie rzucony wyjątek. Podstawowa zasada mówi, że możemy nakładać na siebie dowolne typy wartości, ale na typy wartości nie możemy nakładać typów referencyjnych. Jeśli pole Text1 oznaczone jest poniższym atrybutem: [FieldOffsetAttribute(14)] 1.1 Tworzenie unii 5

26 wówczas w momencie uruchomienia programu zostanie rzucony poniższy wyjątek (zwróćmy uwagę, że kompilator nie wychwyci tego problemu): System.TypeLoadException: Could not load type 'SignedNumberWithText' from assembly 'CSharpRecipes, Version= , Culture=neutral, PublicKeyToken=fe85c3941fbcc4c5' because it contains an object field at offset 14 that is incorrectly aligned or overlapped by a non-object field. W przypadku korzystania w języku C# ze złożonych unii należy zwrócić szczególną uwagę na przesunięcia pól. Zobacz także Temat StructLayoutAttribute Class w dokumentacji MSDN. 1.2 Umożliwianie sortowania typu Problem Mamy typ danych, który przechowywany będzie w postaci elementów na liście List<T> lub SortedList<K,V>. Korzystając z metody List<T>.Sort lub wewnętrznego mechanizmu sortowania klasy SortedList<K,V> chcemy umożliwić sobie niestandardowe sortowanie naszych danych w tablicy. Dodatkowo może zajść potrzeba wykorzystania tego typu danych w kolekcji SortedList. Rozwiązanie Przykład 1-1 demonstruje sposób implementacji interfejsu IComparable<T>. Widoczna w tym przykładzie klasa Square implementuje ten intefejs w taki sposób, że kolekcje List<T> i SortedList<K,V> mogą sortować i wyszukiwać obiekty Square. Przykład 1-1 Umożliwianie sortowania typu poprzez implementację interfejsu IComparable<T> public class Square : IComparable<Square> public Square() public Square(int height, int width) this.height = height; this.width = width; public int Height get; set; 6 Rozdział 1: Klasy i typy generyczne

27 public int Width get; set; public int CompareTo(object obj) Square square = obj as Square; if (square!= null) return CompareTo(square); throw new ArgumentException( "Both objects being compared must be of type Square."); public override string ToString()=> ($"Height: this.height Width: this.width"); public override bool Equals(object obj) if (obj == null) return false; Square square = obj as Square; if(square!= null) return this.height == square.height; return false; public override int GetHashCode() return this.height.gethashcode() this.width.gethashcode(); public static bool operator ==(Square x, Square y) => x.equals(y); public static bool operator!=(square x, Square y) =>!(x == y); public static bool operator <(Square x, Square y) => (x.compareto(y) < 0); public static bool operator >(Square x, Square y) => (x.compareto(y) > 0); public int CompareTo(Square other) long area1 = this.height * this.width; long area2 = other.height * other.width; if (area1 == area2) return 0; else if (area1 > area2) return 1; else if (area1 < area2) return -1; else return -1; 1.2 Umożliwianie sortowania typu 7

28 Omówienie Dzięki implementacji w naszej klasie (lub strukturze) interfejsu IComparable<T> możemy skorzystać z dostępnych w klasach List<T> i SortedList<K,V> algorytmów sortowania. Wcześniej jednak musimy zdefiniować sposób sortowania naszej klasy. Dokonujemy tego w metodzie IComparable<T>.CompareTo. Podczas sortowania listy obiektów Square w ramach wywołania metody List<Square>. Sort lista sortowana jest z wykorzystaniem interfejsu IComparable<Square>. Metoda Add klasy SortedList<K,V> wykorzystuje ten interfejs do sortowania obiektów w czasie dodawania ich do listy SortedList<K,V>. Interfejs IComparer<T> umożliwia sortowanie obiektów w oparciu o różne kryteria, w różnym kontekście. Umożliwia on również sortowanie typów, które nie są naszego autorstwa. Jeśli chcielibyśmy posortować obiekty Square względem ich wysokości, moglibyśmy utworzyć nową klasę o nazwie CompareHeight, widoczną w przykładzie 1-2, która również będzie implementować interfejs IComparer<Square>. Przykład 1-2 Umożliwianie sortowania typu poprzez implementację interfejsu IComparer public class CompareHeight : IComparer<Square> public int Compare(object firstsquare, object secondsquare) Square square1 = firstsquare as Square; Square square2 = secondsquare as Square; if (square1 == null square2 == null) throw (new ArgumentException( "Both parameters must be of type Square.")); else return Compare(firstSquare,secondSquare); #region IComparer<Square> Members public int Compare(Square x, Square y) if (x.height == y.height) return 0; else if (x.height > y.height) return 1; else if (x.height < y.height) return -1; else return -1; 8 Rozdział 1: Klasy i typy generyczne

29 #endregion Klasa ta zostanie przekazana do parametru IComparer procedury Sort. Teraz możemy zdefiniować kilka sposobów sortowania naszych obiektów Square. Zaimplementowana metoda porównująca musi nie tylko być spójna, ale musi też stosować porządek liniowy. Da nam to pewność, że gdy funkcja porównująca zadeklaruje równość dwóch elementów, wówczas będą one całkowicie równe, a tym samym ich równość nie będzie przykładowo wynikiem tego, że jeden z nich jest jedynie nie większy lub nie mniejszy od drugiego. W celu uzyskania jak największej wydajności utrzymuj metodę CompareTo w krótkiej i wydajnej postaci, ponieważ będzie ona wywoływana wielokrotnie przez metody Sort. W przypadku sortowania tablicy z czterema elementami metoda Compare wywoływana jest przykładowo 10 razy. Metoda TestSort widoczna w przykładzie 1-3 demonstruje użycie klas Square i CompareHeight z wykorzystaniem instancji List<Square> i SortedList<int,Square>. Przykład 1-3 Metoda TestSort public static void TestSort() List<Square> listofsquares = new List<Square>() new Square(1,3), new Square(4,3), new Square(2,1), new Square(6,1); // Przetestuj List<String> Console.WriteLine("List<String>"); Console.WriteLine("Original list"); foreach (Square square in listofsquares) Console.WriteLine(square.ToString()); Console.WriteLine(); IComparer<Square> heightcompare = new CompareHeight(); listofsquares.sort(heightcompare); Console.WriteLine("Sorted list using IComparer<Square>=heightCompare"); foreach (Square square in listofsquares) Console.WriteLine(square.ToString()); 1.2 Umożliwianie sortowania typu 9

30 Console.WriteLine(); Console.WriteLine("Sorted list using IComparable<Square>"); listofsquares.sort(); foreach (Square square in listofsquares) Console.WriteLine(square.ToString()); // Przetestuj SortedList var sortedlistofsquares = new SortedList<int,Square>() 0, new Square(1,3), 2, new Square(3,3), 1, new Square(2,1), 3, new Square(6,1); Console.WriteLine(); Console.WriteLine(); Console.WriteLine("SortedList<Square>"); foreach (KeyValuePair<int,Square> kvp in sortedlistofsquares) Console.WriteLine ($"kvp.key : kvp.value"); Powyższy kod wyświetli następujący wynik: List<String> Original list Height:1 Width:3 Height:4 Width:3 Height:2 Width:1 Height:6 Width:1 Sorted list using IComparer<Square>=heightCompare Height:1 Width:3 Height:2 Width:1 Height:4 Width:3 Height:6 Width:1 Sorted list using IComparable<Square> Height:2 Width:1 Height:1 Width:3 Height:6 Width:1 Height:4 Width:3 SortedList<Square> 0 : Height:1 Width:3 10 Rozdział 1: Klasy i typy generyczne

31 1 : Height:2 Width:1 2 : Height:3 Width:3 3 : Height:6 Width:1 Zobacz także Przepis 1.3 oraz temat IComparable<T> Interface w dokumentacji MSDN. 1.3 Umożliwianie przeszukiwania typu Problem Mamy typ danych, który przechowywany będzie w postaci elementów na liście List<T>. Chcemy skorzystać z metody BinarySearch, by umożliwić sobie niestandardowe wyszukiwanie naszych danych na liście. Rozwiązanie Skorzystamy z interfejsów IComparable<T> i IComparer<T>. Klasa Square z przepisu 1.2 implementuje interfejs IComparable<T> w taki sposób, że kolekcje List<T> i SortedList<K,V> mogą sortować i przeszukiwać tablicę lub kolekcję obiektów Square. Omówienie Dzięki implementacji w naszej klasie (lub strukturze) interfejsu IComparable<T> możemy skorzystać z dostępnych w klasach List<T> i SortedList<K,V> algorytmów wyszukiwania. Wcześniej jednak musimy zdefiniować sposób przeszukiwania naszej klasy. Dokonamy tego w metodzie IComparable<T>. CompareTo. Aby zaimplementować metodę CompareTo, zobacz przepis 1.2. Klasa List<T> dostarcza metodę BinarySearch, która dokonuje wyszukiwania na zawartych w tej liście elementach. Elementy te porównywane są z obiektem przekazanym do metody BinarySearch w parametrze obiektu. Klasa SortedList nie zawiera metody BinarySearch; zamiast tego zawiera ona metodę ContainsKey, która dokonuje wyszukiwania binarnego na zawartym na liście kluczu. Metoda ContainsValue klasy SortedList do wyszukiwania wartości wykorzystuje wyszukiwanie liniowe. By wykonać swoją pracę, wyszukiwanie liniowe korzysta z metody Equals elementów w kolekcji SortedList. Metody Compare i CompareTo nie wywierają żadnego wpływu na operację wyszukiwania liniowego wykonywaną w klasie SortedList, jednak mają one wpływ na wyszukiwanie binarne. 1.3 Umożliwianie przeszukiwania typu 11

32 Aby wykonać dokładne wyszukiwanie przy użyciu metody BinarySearch klasy List<T>, musisz najpierw posortować listę List<T> korzystając z jej metody Sort. Jeśli interfejs IComparer<T> przekażesz do metody BinarySearch, musisz również przekazać ten sam interfejs do metody Sort. W innym przypadku metoda BinarySearch może nie być w stanie znaleźć obiektu, którego szukasz. Metoda TestSort, widoczna w przykładzie 1-4, demonstruje użycie klas Square i CompareHeight z instancjami kolekcji List<Square> i SortedList<int,Square>. Przykład 1-4 Umożliwianie przeszukiwania typu public static void TestSearch() List<Square> listofsquares = new List<Square> new Square(1,3), new Square(4,3), new Square(2,1), new Square(6,1); IComparer<Square> heightcompare = new CompareHeight(); // Przetestuj kolekcję List<Square> Console.WriteLine("List<Square>"); Console.WriteLine("Original list"); foreach (Square square in listofsquares) Console.WriteLine(square.ToString()); Console.WriteLine(); Console.WriteLine("Sorted list using IComparer<Square>=heightCompare"); listofsquares.sort(heightcompare); foreach (Square square in listofsquares) Console.WriteLine(square.ToString()); Console.WriteLine(); Console.WriteLine("Search using IComparer<Square>=heightCompare"); int found = listofsquares.binarysearch(new Square(1,3), heightcompare); Console.WriteLine($"Found (1,3): found"); Console.WriteLine(); Console.WriteLine("Sorted list using IComparable<Square>"); listofsquares.sort(); foreach (Square square in listofsquares) Console.WriteLine(square.ToString()); 12 Rozdział 1: Klasy i typy generyczne

33 Console.WriteLine(); Console.WriteLine("Search using IComparable<Square>"); found = listofsquares.binarysearch(new Square(6,1)); // Use IComparable Console.WriteLine($"Found (6,1): found"); // Przetestuj kolekcję SortedList<Square> var sortedlistofsquares = new SortedList<int,Square>() 0, new Square(1,3), 2, new Square(4,3), 1, new Square(2,1), 4, new Square(6,1); Console.WriteLine(); Console.WriteLine("SortedList<Square>"); foreach (KeyValuePair<int,Square> kvp in sortedlistofsquares) Console.WriteLine ($"kvp.key : kvp.value"); Console.WriteLine(); bool founditem = sortedlistofsquares.containskey(2); Console.WriteLine($"sortedListOfSquares.ContainsKey(2): founditem"); // Nie wykorzystuje interfejsów IComparer lub IComparable, // lecz korzysta z wyszukiwania liniowego z metodą Equals, // która nie została przeciążona Console.WriteLine(); Square value = new Square(6,1); founditem = sortedlistofsquares.containsvalue(value); Console.WriteLine("sortedListOfSquares.ContainsValue " + $"(new Square(6,1)): founditem"); Powyższy kod generuje następujący wynik: List"Square> Original list Height:1 Width:3 Height:4 Width:3 Height:2 Width:1 Height:6 Width:1 Sorted list using IComparer"Square>=heightCompare Height:1 Width:3 Height:2 Width:1 Height:4 Width:3 Height:6 Width:1 1.3 Umożliwianie przeszukiwania typu 13

34 Search using IComparer"Square>=heightCompare Found (1,3): 0 Sorted list using IComparable"Square> Height:2 Width:1 Height:1 Width:3 Height:6 Width:1 Height:4 Width:3 Search using IComparable"Square> Found (6,1): 2 SortedList"Square> 0 : Height:1 Width:3 1 : Height:2 Width:1 2 : Height:4 Width:3 4 : Height:6 Width:1 sortedlistofsquares.containskey(2): True sortedlistofsquares.containsvalue(new Square(6,1)): True Zobacz także Przepis 1.2 oraz tematy IComparable<T> Interface i IComparer<T> Interface w dokumentacji MSDN. 1.4 Zwracanie z metody wielu elementów Problem W wielu przypadkach zwracanie przez metodę pojedynczej wartości może okazać się niewystarczające. Potrzebujemy sposobu, dzięki któremu z metody będziemy mogli zwrócić więcej niż jeden element. Rozwiązanie Parametrom metody, które posłużą nam do zwracania elementów, przypiszemy słowo kluczowe out. Poniższa metoda przyjmuje parametr inputshape i na podstawie podanej wartości oblicza wysokość (height), szerokość (width) oraz głębokość (depth): public void ReturnDimensions(int inputshape, out int height, out int width, out int depth) 14 Rozdział 1: Klasy i typy generyczne

35 height = 0; width = 0; depth = 0; // Oblicz wysokość, szerokość i głębokość z podanej wartości inputshape. Metoda ta może zostać wywołana w następujący sposób: // Zadeklaruj parametry wyjściowe. int height; int width; int depth; // Wywołaj metodę i zwróć wysokość, szerokość i głębokość. Obj.ReturnDimensions(1, out height, out width, out depth); Kolejnym sposobem jest zwrócenie klasy lub struktury zawierającej wszystkie zwracane wartości. W poniższym przykładzie zmodyfikowaliśmy poprzednią metodę, tak by zamiast argumentów out zwracała tym razem strukturę: public Dimensions ReturnDimensions(int inputshape) // Konstruktor domyślny automatycznie ustawia wartości struktury na 0. Dimensions objdim = new Dimensions(); // Oblicz objdim.height, objdim.width, objdim.depth // bazując na wartości inputshape... return objdim; Sama struktura Dimensions zdefiniowana została poniżej: public struct Dimensions public int Height; public int Width; public int Depth; Wywołanie tej metody byłoby następujące: // Wywołaj metodę i zwróć wysokość, szerokość i głębokość. Dimensions objdim = obj.returndimensions(1); Zamiast zwracać zdefiniowaną przez użytkownika klasę lub strukturę, możemy skorzystać z obiektu Tuple, który zawierał będzie wszystkie zwracane wartości. Ponownie zmodyfikowaliśmy poprzednią metodę, która tym razem zwraca obiekt Tuple: 1.4 Zwracanie z metody wielu elementów 15

36 public Tuple<int, int, int> ReturnDimensionsAsTuple(int inputshape) // Oblicz objdim.height, objdim.width oraz objdim.depth na podstawie // wartości inputshape, przykładowo 5, 10, 15 // Utwórz obiekt Tuple z wyliczonymi wartościami var objdim = Tuple.Create<int, int, int>(5, 10, 15); return (objdim); Powyższą metodę możemy wywołać w następujący sposób: // Wywołaj metodę i zwróć wysokość, szerokość i głębokość. Tuple<int, int, int> objdim = obj.returndimensions(1); Omówienie Oznaczanie parametru w sygnaturze metody słowem kluczowym out wskazuje, że parametr ten zostanie zainicjowany i zwrócony przez tę metodę. Sztuczka ta przydaje się, gdy od metody wymaga się zwrócenia więcej niż jednej wartości. Sama metoda jest w stanie zwrócić co najwyżej jedną wartość, ale dzięki słowu kluczowemu out możemy wyznaczyć kilka dodatkowych parametrów, które traktowane będą jak wartość zwracana. Wskazanie parametru jako wartości zwracanej polega na oznaczeniu go w sygnaturze metody słowem kluczowym out, jak w poniższym przykładzie: public void ReturnDimensions(int inputshape, out int height, out int width, out int depth)... By móc prawidłowo wywołać tę metodę, w podobny sposób musimy również oznaczyć argumenty przy jej wywołaniu: obj.returndimensions(1, out height, out width, out depth); W powyższym wywołaniu nie zachodzi potrzeba inicjalizacji argumentów out. Możemy je po prostu zadeklarować i przesłać do metody ReturnDimensions. Bez względu na to, czy zostały one zainicjowane przed wywołaniem, czy też nie, musimy je zainicjować przed użyciem wewnątrz metody ReturnDimensions. Nawet jeśli nie korzystamy z nich w każdym możliwym przepływie tej metody, ich wcześniejsza inicjalizacja jest wymagana. To właśnie dlatego metoda ta rozpoczyna się od trzech poniższych linii kodu: 16 Rozdział 1: Klasy i typy generyczne

37 height = 0; width = 0; depth = 0; Nasuwa się tu pytanie, dlaczego zamiast parametru out nie skorzystaliśmy z parametru ref, który również pozwala metodzie na zmodyfikowanie wartości oznaczonych w ten sposób argumentów. Jest tak dlatego, że parametry out czynią kod niejako samodokumentującym się. Gdy napotykany jest parametr out, wówczas zachowuje się on jak wartość zwracana. Dodatkowo parameter out, w przeciwieństwie do parametru ref, nie wymaga żadnej dodatkowej pracy związanej z jego inicjalizacją przed przekazaniem do metody. Parametr out nie musi być pakowany (boxing) przy wywoływaniu metody. Parametr ten pakowany jest raz, gdy metoda zwraca dane do wywołującego. Jakikolwiek inny rodzaj wywołania (przez wartość lub przez referencję z użyciem słowa kluczowego ref) wymaga dwustronnego pakowania wartości. Korzystanie ze słowa kluczowego out w scenariuszach pakowania podnosi wydajność zdalnej komunikacji. Parametr out przydaje się, gdy zachodzi potrzeba zwrócenia niewielkiej liczby wartości. Jeśli jednak musimy zwrócić 4, 5, 6 lub więcej wartości, metoda ta staje się mało zaradna. Innym rozwiązaniem umożliwiającym zwracanie większej liczby wartości jest utworzenie i zwrócenie zdefiniowanej przez użytkownika klasy/struktury, bądź też skorzystanie z obiektu Tuple, który będzie w sobie zawierać wszystkie konieczne do zwrócenia wartości. Zwracanie wartości z użyciem klasy lub struktury jest bardzo proste. Tworzymy określony typ (w naszym wypadku strukturę), jak w poniższym przykładzie: public struct Dimensions public int Height; public int Width; public int Depth; Wypełniamy strukturę konkretnymi danymi, a następnie zwracamy ją z wnętrza metody, jak zostało to przedstawione w Rozwiązaniu tego przepisu. Drugi sposób, czyli wykorzystanie obiektu Tuple, jest jeszcze bardziej eleganckim rozwiązaniem. Obiekty Tuple mogą przechowywać dowolną liczbę wartości, które niekoniecznie muszą być tego samego typu. Co więcej, przechowywane przez nas dane w obiekcie Tuple są niezmienne. Po dodaniu danych do obiektu Tuple z użyciem jego konstruktora lub statycznej metody Create danych tych nie będziemy mogli zmienić. 1.4 Zwracanie z metody wielu elementów 17

38 Obiekty Tuple mogą przyjmować do ośmu oddzielnych wartości. Jeśli zachodzi potrzeba zwrócenia więcej niż ośmiu wartości, musimy się wówczas posłużyć specjalną klasą Tuple: Tuple<T1, T2, T3, T4, T5, T6, T7, TRest> Class Chcąc utworzyć obiekt klasy Tuple z więcej niż ośmioma wartościami, nie możemy skorzystać z jej statycznej metody Create. Zamiast tego musimy posłużyć się konstruktorem tej klasy. W poniższym przykładzie tworzony jest obiekt Tuple przyjmujący 10 wartości typu całkowitego: var values = new Tuple<int, int, int, int, int, int, int, Tuple<int, int, int>> ( 1, 2, 3, 4, 5, 6, 7, new Tuple<int, int, int> (8, 9, 10)); Oczywiście na końcach zagnieżdzonych obiektów Tuple również możemy wstawiać kolejne obiekty, tworząc w ten sposób jeden wielki obiekt Tuple, zdolny do przechowywania dowolnej liczby wartości. Zobacz także Tematy Tuple Class i Tuple<T1, T2, T3, T4, T5, T6, T7, TRest> Class w dokumentacji MSDN. 1.5 Parsowanie parametrów wiersza poleceń Problem Chcemy, by nasza aplikacja przyjmowała jeden lub więcej parametrów wiersza poleceń w standardowym formacie (opisanym dalej w części Omówienie tego przepisu). Musimy uzyskać dostęp i sparsować wszystkie parametry przesłane do aplikacji z wiersza poleceń. Rozwiązanie Aby ułatwić sobie parsowanie parametrów wiersza poleceń, w przykładzie 1-5 posłużymy się klasami Argument, ArgumentDefi nition i ArgumentSemanticAnalyzer. Ich kod znajduje się poniżej. Przykład 1-5 Klasa Argument using System; using System.Diagnostics; using System.Linq; using System.Collections.ObjectModel; 18 Rozdział 1: Klasy i typy generyczne

39 public sealed class Argument public string Original get; public string Switch get; private set; public ReadOnlyCollection<string> SubArguments get; private List<string> subarguments; public Argument(string original) Original = original; Switch = string.empty; subarguments = new List<string>(); SubArguments = new ReadOnlyCollection<string>(subArguments); Parse(); private void Parse() if (string.isnullorempty(original)) return; char[] switchchars = '/', '-' ; if (!switchchars.contains(original[0])) return; string switchstring = Original.Substring(1); string subargsstring = string.empty; int colon = switchstring.indexof(':'); if (colon >= 0) subargsstring = switchstring.substring(colon + 1); switchstring = switchstring.substring(0, colon); Switch = switchstring; if (!string.isnullorempty(subargsstring)) subarguments.addrange(subargsstring.split(';')); // Zestaw predykatów, który dostarcza cennych informacji na swój temat. // Zaimplementowano z użyciem operatorów lambda public bool IsSimple => SubArguments.Count == 0; public bool IsSimpleSwitch =>!string.isnullorempty(switch) && SubArguments.Count == 0; 1.5 Parsowanie parametrów wiersza poleceń 19

40 public bool IsCompoundSwitch =>!string.isnullorempty(switch) && SubArguments.Count == 1; public bool IsComplexSwitch =>!string.isnullorempty(switch) && SubArguments.Count > 0; public sealed class ArgumentDefinition public string ArgumentSwitch get; public string Syntax get; public string Description get; public Func<Argument, bool> Verifier get; public ArgumentDefinition(string argumentswitch, string syntax, string description, Func<Argument, bool> verifier) ArgumentSwitch = argumentswitch.toupper(); Syntax = syntax; Description = description; Verifier = verifier; public bool Verify(Argument arg) => Verifier(arg); public sealed class ArgumentSemanticAnalyzer private List<ArgumentDefinition> argumentdefinitions = new List<ArgumentDefinition>(); private Dictionary<string, Action<Argument>> argumentactions = new Dictionary<string, Action<Argument>>(); public ReadOnlyCollection<Argument> UnrecognizedArguments get; private set; public ReadOnlyCollection<Argument> MalformedArguments get; private set; public ReadOnlyCollection<Argument> RepeatedArguments get; private set; public ReadOnlyCollection<ArgumentDefinition> ArgumentDefinitions => new ReadOnlyCollection<ArgumentDefinition>(argumentDefinitions); public IEnumerable<string> DefinedSwitches => from argumentdefinition in argumentdefinitions select argumentdefinition.argumentswitch; public void AddArgumentVerifier(ArgumentDefinition verifier) => argumentdefinitions.add(verifier); public void RemoveArgumentVerifier(ArgumentDefinition verifier) 20 Rozdział 1: Klasy i typy generyczne

41 var verifierstoremove = from v in argumentdefinitions where v.argumentswitch == verifier.argumentswitch select v; foreach (var v in verifierstoremove) argumentdefinitions.remove(v); public void AddArgumentAction(string argumentswitch, Action<Argument> action) => argumentactions.add(argumentswitch, action); public void RemoveArgumentAction(string argumentswitch) if (argumentactions.keys.contains(argumentswitch)) argumentactions.remove(argumentswitch); public bool VerifyArguments(IEnumerable<Argument> arguments) // Brak parametru do zweryfikowania, błąd. if (!argumentdefinitions.any()) return false; // Sprawdź, czy któryś z argumentów nie został zdefiniowany this.unrecognizedarguments = ( from argument in arguments where!definedswitches.contains(argument.switch.toupper()) select argument).tolist().asreadonly(); if (this.unrecognizedarguments.any()) return false; // Sprawdź wszystkie argumenty, których przełącznik pasuje // do znanego przełącznika, przy uwzględnieniu, że nasz // predykat poprawności jest fałszywy. this.malformedarguments = ( from argument in arguments join argumentdefinition in argumentdefinitions on argument.switch.toupper() equals argumentdefinition.argumentswitch where!argumentdefinition.verify(argument) select argument).tolist().asreadonly(); if (this.malformedarguments.any()) return false; // Posortuj argumenty w "grupy" względem ich przełączników, // zlicz wszystkie grupy, a następnie wybierz te, // które zawierają więcej niż jeden element. 1.5 Parsowanie parametrów wiersza poleceń 21

42 // Uzyskamy wówczas listę elementów tylko do odczytu. this.repeatedarguments = (from argumentgroup in from argument in arguments where!argument.issimple group argument by argument.switch.toupper() where argumentgroup.count() > 1 select argumentgroup).selectmany(ag => ag).tolist().asreadonly(); if (this.repeatedarguments.any()) return false; return true; public void EvaluateArguments(IEnumerable<Argument> arguments) // Teraz już tylko aplikujemy każdą z akcji: foreach (Argument argument in arguments) argumentactions[argument.switch.toupper()](argument); public string InvalidArgumentsDisplay() StringBuilder builder = new StringBuilder(); builder.appendformat($"invalid arguments: Environment.NewLine"); // Dodaj nierozpoznane argumenty FormatInvalidArguments(builder, this.unrecognizedarguments, "Unrecognized argument: 01"); // Dodaj niepoprawne argumenty FormatInvalidArguments(builder, this.malformedarguments, "Malformed argument: 01"); // Powtórzone argumenty chcemy pogrupować w celu wyświetlenia, // więc pogrupujemy je według przełączników, a następnie dodamy je // do tworzonego łańcucha znaków. var argumentgroups = from argument in this.repeatedarguments group argument by argument.switch.toupper() into ag select new Switch = ag.key, Instances = ag; foreach (var argumentgroup in argumentgroups) builder.appendformat($"repeated argument: argumentgroup.switchenvironment.newline"); FormatInvalidArguments(builder, argumentgroup.instances.tolist(), "\t01"); 22 Rozdział 1: Klasy i typy generyczne

43 return builder.tostring(); private void FormatInvalidArguments(StringBuilder builder, IEnumerable<Argument> invalidarguments, string errorformat) if (invalidarguments!= null) foreach (Argument argument in invalidarguments) builder.appendformat(errorformat, argument.original, Environment.NewLine); Poniższy przykład pokazuje nam, w jaki sposób możemy korzystać z tych klas do przetwarzania wiersza poleceń: public static void Main(string[] argumentstrings) var arguments = (from argument in argumentstrings select new Argument(argument)).ToArray(); Console.Write("Command line: "); foreach (Argument a in arguments) Console.Write($"a.Original "); Console.WriteLine(""); ArgumentSemanticAnalyzer analyzer = new ArgumentSemanticAnalyzer(); analyzer.addargumentverifier( new ArgumentDefinition("output", "/output:[path to output]", "Specifies the location of the output file.", x => x.iscompoundswitch)); analyzer.addargumentverifier( new ArgumentDefinition("trialMode", "/trialmode", "If this is specified it places the product into trial mode", x => x.issimpleswitch)); analyzer.addargumentverifier( new ArgumentDefinition("DEBUGOUTPUT", "/debugoutput:[value1];[value2];[value3]", 1.5 Parsowanie parametrów wiersza poleceń 23

44 "A listing of the files the debug output " + "information will be written to", x => x.iscomplexswitch)); analyzer.addargumentverifier( new ArgumentDefinition("", "[literal value]", "A literal value", x => x.issimple)); if (!analyzer.verifyarguments(arguments)) string invalidarguments = analyzer.invalidargumentsdisplay(); Console.WriteLine(invalidArguments); ShowUsage(analyzer); return; // Ustaw obiekty przechowujące wyniki parsowania string output = string.empty; bool trialmode = false; IEnumerable<string> debugoutput = null; List<string> literals = new List<string>(); // Dla każdego parsowanego argumentu chcemy zastosować akcję, // więc dodamy je do analizatora. analyzer.addargumentaction("output", x => output = x.subarguments[0]; ); analyzer.addargumentaction("trialmode", x => trialmode = true; ); analyzer.addargumentaction("debugoutput", x => debugoutput = x.subarguments; ); analyzer.addargumentaction("", x=>literals.add(x.original);); // Sprawdź argumenty i wykonaj akcje analyzer.evaluatearguments(arguments); // Wyświetl wyniki Console.WriteLine(""); Console.WriteLine($"OUTPUT: output"); Console.WriteLine($"TRIALMODE: trialmode"); if (debugoutput!= null) foreach (string item in debugoutput) Console.WriteLine($"DEBUGOUTPUT: item"); foreach (string literal in literals) 24 Rozdział 1: Klasy i typy generyczne

45 Console.WriteLine($"LITERAL: literal"); public static void ShowUsage(ArgumentSemanticAnalyzer analyzer) Console.WriteLine("Program.exe allows the following arguments:"); foreach (ArgumentDefinition definition in analyzer.argumentdefinitions) Console.WriteLine($"\tdefinition.ArgumentSwitch: (definition.description)environment.newline \tsyntax: definition.syntax"); Omówienie Zanim będziemy mogli sparsować parametry wiersza poleceń, musimy uzgodnić jakiś wspólny format. Zaproponowany w tym przepisie format bazuje na formacie wiersza poleceń dla kompilatora języka Visual C#.NET. Format ten zdefiniowany jest następująco: Wszystkie argumenty wiersza poleceń rozdzielone są co najmnej jednym białym znakiem. Każdy z argumentów może rozpoczynać się od znaku lub /, lecz nie obu na raz. Jeśli argument nie spełnia tego formatu, wówczas uznaje się go za literał, będący przykładowo nazwą pliku. Każdy argument rozpoczynający się od znaku - lub / może zostać podzielony na przełącznik, po którym następuje dwukropek, a po nim jeden lub więcej argumentów rozdzielonych między sobą znakiem ; (średnik). Parametr wiersza pleceń -sw:arg1;arg2;arg3 dzieli się na przełącznik (sw) oraz trzy argumenty (arg1, arg2 oraz arg3). Zwróćmy uwagę, że w pełnym argumencie nie powinien występować żaden odstęp. W przeciwnym przypadku parser uzna go za dwa lub więcej argumentów. Łańcuchy znaków ograniczone cudzysłowem, np. "c:\test\fi le.log", zostaną cudzysłowu pozbawione. Procesu tego dokona funkcja systemu operacyjnego, która interpretuje argumenty przysłane do naszej aplikacji. Łańcuchy znaków ograniczone znakiem apostrofu nie podlegają temu zabiegowi. Aby zachować znaki codzysłowu, należy je poprzedzić znakiem sekwencji ucieczki \ (odwrotnym ukośnikiem). Znak \ obsługiwany jest jako znak sekwencji ucieczki tylko wtedy, gdy poprzedza znak cudzysłowu. W takim wypadku wyświetlany jest wyłącznie znak cudzysłowu. 1.5 Parsowanie parametrów wiersza poleceń 25

46 Znak ^ wykorzystywany jest przez parser wiersza poleceń środowiska uruchomieniowego jako znak specjalny. Na szczęście większość z tych rzeczy obsługiwanych jest przez parser wiersza poleceń środowiska uruchomieniowego, zanim jeszcze nasza aplikacja otrzyma indywidualne i przeparsowane argumenty. Parser wiersza poleceń środowiska uruchomieniowego przekazuje do punktu startowego naszej aplikacji kolekcję string[] zawierającą każdy z przeparsowanych argumentów. Punkt ten może przyjmować jedną z poniższych form: public static void Main() public static int Main() public static void Main(string[] args) public static int Main(string[] args) Pierwsze dwie deklaracje nie przyjmują żadnych argumentów, natomiast dwie ostatnie przyjmują tablicę przeparsowanych argumentów wiersza poleceń. Zwróćmy uwagę, że właściwość statyczna Environment.CommandLine również zwraca łańcuch zawierający pełną listę argumentów wiersza poleceń, zaś metoda statyczna Environment. GetCommandLineArgs zwraca tablicę łańcuchów zawierających przeparsowane argumenty wiersza poleceń. Trzy klasy zaprezentowane w Rozwiązaniu niniejszego przepisu stanowią poszczególne fazy pracy z argumentami wiersza poleceń: Argument Enkapsuluje pojedynczy argument wiersza poleceń i odpowiada za jego przeparsowanie. ArgumentDefi nition Definiuje argument, który będzie prawidłowy dla bieżącego wiersza poleceń. ArgumentSemanticAnalyzer Dokonuje weryfikacji i pozyskuje argumenty w oparciu o przygotowane definicje argumentów ArgumentDefi nition. Przekazanie do tej aplikacji poniższych argumentów wiersza poleceń: MyApp c:\input\infile.txt -output:d:\outfile.txt -trialmode wygeneruje w procesie parsowania następujące przełączniki i argumenty: Command line: c:\input\infile.txt -output:d:\outfile.txt -trialmode OUTPUT: d:\outfile.txt TRIALMODE: True LITERAL: c:\input\infile.txt 26 Rozdział 1: Klasy i typy generyczne

47 Jeśli parametry wiersza poleceń nie zostaną poprawnie wprowadzone (przykładowo zapomnimy dodać argument do przełącznika output), wówczas otrzymamy następujące wyjście: Command line: c:\input\infile.txt -output: -trialmode Invalid arguments: Malformed argument: -output Program.exe allows the following arguments: OUTPUT: (Specifies the location of the output file.) Syntax: /output:[path to output] TRIALMODE: (If this is specified, it places the product into trial mode) Syntax: /trialmode DEBUGOUTPUT: (A listing of the files the debug output information will be written to) Syntax: /debugoutput:[value1];[value2];[value3] : (A literal value) Syntax: [literal value] W kodzie znajduje się kilka elementów, które zdecydowanie warto omówić. Każda instancja argumentu Argument musi być w stanie ustalić kilka rzeczy na swój temat. Z tego względu w klasie Argument wyeksponowany został zestaw predykatów, które podadzą nam kilka cennych informacji na temat danego argumentu. Klasa ArgumentSemanticAnalyzer skorzysta z tych właściwości w celu ustalenia charakterystyki konkretnego argumentu: public bool IsSimple => SubArguments.Count == 0; public bool IsSimpleSwitch =>!string.isnullorempty(switch) && SubArguments.Count == 0; public bool IsCompoundSwitch =>!string.isnullorempty(switch) && SubArguments.Count == 1; public bool IsComplexSwitch =>!string.isnullorempty(switch) && SubArguments.Count > 0; Więcej informacji na temat wyrażeń lambda znajdziesz we wstępie do Rozdziału 4. Zobacz także przepis 1.16, w którym znajdziesz omówienie sposobu wykorzystania wyrażeń lambda pod kątem tworzenia domknięć. W kilku miejscach w kodzie na wynikach zapytań LINQ wywoływane są metody ToArray lub ToList: var arguments = (from argument in argumentstrings select new Argument(argument)).ToArray(); 1.5 Parsowanie parametrów wiersza poleceń 27

48 Jest tak, ponieważ wyniki zapytań korzystają z odroczonego wykonania, co oznacza, że wyniki te obliczane są w leniwy sposób, a przy każdym kolejnym dostępie do nich są one obliczane na nowo. Korzystając z metody ToArray lub ToList niejako wymuszamy ewaluację tych wyników, co skutkuje utworzeniem ich kopii, która nie będzie ponownie obliczana przy każdym jej użyciu. Logika zapytań nie wie, czy kolekcja, nad którą właśnie pracuje, ulega zmianie, więc za każdym razem musi dokonywać ponownych obliczeń, chyba że przy użyciu wspomnianych metod utworzymy sobie kopię tych wyników. Chcąc zweryfikować, czy argumenty te są poprawne, musimy utworzyć definicję argumentu ArgumentDefi nition i z pomocą analizatora ArgumentSemanticAnalyzer powiązać ją z każdym akceptowanym typem argumentu ArgumentSemanticAnalyzer: ArgumentSemanticAnalyzer analyzer = new ArgumentSemanticAnalyzer(); analyzer.addargumentverifier( new ArgumentDefinition("output", "/output:[path to output]", "Specifies the location of the output file.", x => x.iscompoundswitch)); analyzer.addargumentverifier( new ArgumentDefinition("trialMode", "/trialmode", "If this is specified it places the product into trial mode", x => x.issimpleswitch)); analyzer.addargumentverifier( new ArgumentDefinition("DEBUGOUTPUT", "/debugoutput:[value1];[value2];[value3]", "A listing of the files the debug output " + "information will be written to", x => x.iscomplexswitch)); analyzer.addargumentverifier( new ArgumentDefinition("", "[literal value]", "A literal value", x => x.issimple)); Każda definicja argumentu ArgumentDefi nition składa się z czterech części: przełącznika argumentu, łańcucha wskazującego składnię argumentu, opisu argumentu oraz predykatu weryfikacji. Informacje te mogą zostać wykorzystane do weryfikacji argumentu, jak w poniższym przykładzie: // Sprawdź wszystkie argumenty, których przełącznik pasuje // do znanego przełącznika, przy uwzględnieniu, że nasz // predykat poprawności jest fałszywy. this.malformedarguments = ( from argument in arguments 28 Rozdział 1: Klasy i typy generyczne

49 join argumentdefinition in argumentdefinitions on argument.switch.toupper() equals argumentdefinition.argumentswitch where!argumentdefinition.verify(argument) select argument).tolist().asreadonly(); Definicje argumentu ArgumentDefinition umożliwiają nam również utworzenie w programie dedykowanej metody użycia: public static void ShowUsage(ArgumentSemanticAnalyzer analyzer) Console.WriteLine("Program.exe allows the following arguments:"); foreach (ArgumentDefinition definition in analyzer.argumentdefinitions) Console.WriteLine("\t0: (1)2\tSyntax: 3", definition.argumentswitch, definition.description, Environment.NewLine,definition.Syntax); Aby pozyskać wartości argumentów w celu ich użycia, musimy wyodrębnić te informacje z przeparsowanych argumentów. W kontekście przykładu z Rozwiązania potrzebowalibyśmy następujących informacji: // Ustaw obiekty przechowujące wyniki parsowania string output = string.empty; bool trialmode = false; IEnumerable<string> debugoutput = null; List<string> literals = new List<string>(); W jaki sposób wartości te zostaną wstawione? Każdy Argument musimy powiązać z konkretną akcją, dzięki czemu będziemy mogli ustalić, w jaki sposób wartość powinna zostać pozyskana z danej instancji Argument. Akcja jest predykatem, a że możemy wykorzystać tutaj praktycznie dowolny predykat, jest to wyjątkowo potężny mechanizm. Poniższy kod definiuje wspomniane akcje i wiąże je z argumentami Argument z użyciem analizatora ArgumentSemanticAnalyzer: // Dla każdego parsowanego argumentu chcemy zastosować akcję, // więc dodamy je do analizatora. analyzer.addargumentaction("output", x => output = x.subarguments[0]; ); analyzer.addargumentaction("trialmode", x => trialmode = true; ); analyzer.addargumentaction("debugoutput", x => debugoutput = x.subarguments;); analyzer.addargumentaction("", x=>literals.add(x.original);); 1.5 Parsowanie parametrów wiersza poleceń 29

50 Teraz, gdy już wszystkie akcje zostały przygotowane, wartości możemy pozyskać z użyciem metody EvaluateArguments na analizatorze ArgumentSemanticAnalyzer: // Sprawdź argumenty i wykonaj akcje analyzer.evaluatearguments(arguments); Dzięki wykonaniu się akcji argumenty zostały wstawione, przez co program może się już uruchomić z ich wartościami: // Uruchom program przekazując mu wartości argumentów: Program program = new Program(output, trialmode, debugoutput, literals); program.run(); Proces weryfikacji argumentów wykorzystuje komponent LINQ do odpytywania nierozpoznanych, źle sformatowanych lub powtarzających się argumentów. Pojawienie się argumentu w takiej właśnie formie skutkować będzie błędem przekazania argumentów: public bool VerifyArguments(IEnumerable<Argument> arguments) // Brak parametru do zweryfikowania, błąd. if (!argumentdefinitions.any()) return false; // Sprawdź, czy któryś z argumentów nie został zdefiniowany this.unrecognizedarguments = ( from argument in arguments where!definedswitches.contains(argument.switch.toupper()) select argument).tolist().asreadonly(); if (this.unrecognizedarguments.any()) return false; // Sprawdź wszystkie argumenty, których przełącznik pasuje // do znanego przełącznika, przy uwzględnieniu, że nasz // predykat poprawności jest fałszywy. this.malformedarguments = ( from argument in arguments join argumentdefinition in argumentdefinitions on argument.switch.toupper() equals argumentdefinition.argumentswitch where!argumentdefinition.verify(argument) select argument).tolist().asreadonly(); if (this.malformedarguments.any()) return false; // Posortuj argumenty w "grupy" względem ich przełączników, // zlicz wszystkie grupy, a następnie wybierz te, // które zawierają więcej niż jeden element. // Uzyskamy wówczas listę elementów tylko do odczytu. 30 Rozdział 1: Klasy i typy generyczne

51 this.repeatedarguments = (from argumentgroup in from argument in arguments where!argument.issimple group argument by argument.switch.toupper() where argumentgroup.count() > 1 select argumentgroup).selectmany(ag => ag).tolist(). AsReadOnly(); if (this.repeatedarguments.any()) return false; return true; Zwróćmy uwagę, że zrozumienie każdej z faz weryfikacji jest w tym wypadku znacznie łatwiejsze, niż gdybyśmy zamiast zapytaniami LINQ posłużyli się wieloma zagnieżdżonymi pętlami, instrukcjami wyboru, metodami IndexOf lub pozostałymi mechanizmami. Każde zapytanie precyzyjnie określa w języku domeny problemu zadanie, jakie stara się zrealizować. Technologia LINQ została zaprojektowana pod kątem problemów, w których dane muszą zostać posortowane, przeszukane, pogrupowane, przefiltrowane i poddane projekcji. Wykorzystaj to! Zobacz także Tematy Main i Command-Line Arguments w dokumentacji MSDN. 1.6 Inicjowanie stałego pola w czasie wykonywania Problem Pole oznaczone jako const może zostać zainicjowane wyłącznie na etapie kompilacji. My jednak chcemy zaincjalizować pole do właściwej wartości w czasie działania programu, a nie podczas kompilacji. Pole to musi przez resztę życia aplikacji zachowywać się tak, jak gdyby było ono polem stałym. Rozwiązanie Wartość stałą w kodzie możemy zadeklarować na dwa sposoby. Możemy to zrobić z wykorzystaniem pola readonly lub z użyciem pola const. Oba te pola mają swoje wady 1.6 Inicjowanie stałego pola w czasie wykonywania 31

52 i zalety. Jeśli jednak zachodzi potrzeba zainicjowania stałego pola w czasie wykonywania programu, wówczas będziemy musieli skorzystać z pola readonly: public class Foo public readonly int bar; public Foo() public Foo(int constinitvalue) bar = constinitvalue; // Reszta klasy... Dokonanie tego z użyciem pola const nie jest możliwe. Pole const może zostać zainicjowane wyłącznie na etapie kompilacji: public class Foo public const int bar; // Ta linia spowoduje błąd podczas kompilacji. public Foo() public Foo(int constinitvalue) bar = constinitvalue; // Ta linia również spowoduje błąd podczas kompilacji. // Reszta klasy... Omówienie Pole readonly umożliwia inicjalizację (wyłącznie w konstruktorze) w czasie działania programu, podczas gdy pole const musi zostać zainicjowane w procesie kompilacji. Z tego względu implementacja pola readonly jest jedynym sposobem inicjalizacji stałego pola w czasie działania programu. Pole readonly możemy zainicjować na dwa sposoby. Pierwszy sposób to dodanie inicjalizatora bezpośrednio do pola: public readonly int bar = 100; Drugi sposób to inicjalizacja pola readonly w konstruktorze. Podejście to zostało przedstawione w kodzie rozwiązania dla tego przepisu. Spójrzmy na poniższą klasę: public class Foo 32 Rozdział 1: Klasy i typy generyczne

53 public readonly int x; public const int y = 1; public Foo() public Foo(int roinitvalue) x = roinitvalue; // Reszta klasy... Klasa ta kompiluje się do następującego kodu języka pośredniego IL (Intermediate Language):.class auto ansi nested public beforefieldinit Foo extends [mscorlib]system.object.field public static literal int32 y = int32(0x ) // <<-- pole const.field public initonly int32 x // <<-- pole readonly.method public hidebysig specialname rtspecialname instance void.ctor(int32 roinitvalue) cil managed // Code size 16 (0x10).maxstack 8 IL_0000: ldarg.0 IL_0001: call instance void [mscorlib]system.object::.ctor() IL_0006: nop IL_0007: nop IL_0008: ldarg.0 IL_0009: ldarg.1 IL_000a: stfld int32 CSharpRecipes.ClassesAndGenerics/Foo::x IL_000f: ret // end of method Foo::.ctor.method public hidebysig specialname rtspecialname instance void.ctor() cil managed // Code size 9 (0x9).maxstack 8 IL_0000: ldarg.0 IL_0001: call instance void [mscorlib]system.object::.ctor() IL_0006: nop IL_0007: nop IL_0008: ret // end of method Foo::.ctor // End of class Foo 1.6 Inicjowanie stałego pola w czasie wykonywania 33

54 Zwróćmy uwagę, że pole const kompilowane jest do pola static, zaś pole readonly kompilowane jest do pola instance. Tym samym, by uzyskać dostęp do pola const, wymagana jest jedynie nazwa klasy. Niewątpliwą wadą pól const w przeciwieństwie do pól readonly jest to, że pola const nie biorą czynnego udziału w procesie wersjonowania. Jeśli przebudujesz komponent ze zdefiniowanym polem const i w przyszłej wersji wartość tego pola const ulegnie zmianie, wówczas żaden inny komponent wykorzystujący tę starą wersję nie wychwyci nowej wartości. Jeśli więc istnieje jakiekolwiek prawdopodobieństwo, że pole ulegnie w przyszłości zmianie, nie definiuj go jako pola const. Poniższy kod pokazuje, w jaki sposób należy korzystać z pola readonly z wykorzystaniem instancji klasy: Foo obj1 = new Foo(100); Console.WriteLine(obj1.bar); Zobacz także Słowa kluczowe const i readonly w dokumentacji MSDN. 1.7 Tworzenie klonowalnych klas Problem Potrzebujemy metody do wykonywania pobieżnego, dokładnego lub obu rodzajów klonowań na typie danych mogącym odnosić się do innych typów, przy czym nie chcemy korzystać z interfejsu ICloneable, jako że narusza on zasady projektowania aplikacji.net. Rozwiązanie Aby rozwiązać problem związany z korzystaniem z interfejsu ICloneable, stworzymy dwie dodatkowe instancje, które posłużą nam do ustalenia wzoru kopiowania: IShallowCopy<T> oraz IDeepCopy<T>: public interface IShallowCopy<T> T ShallowCopy(); public interface IDeepCopy<T> 34 Rozdział 1: Klasy i typy generyczne

C# 6.0 Księga przepisów

C# 6.0 Księga przepisów C# 6.0 Księga przepisów Jay Hilyard & Stephen Teilhet przekład: Krzysztof Kapustka, Joanna Zatorska APN Promise Warszawa 2015 Spis treści Wstęp........................................................................xi

Bardziej szczegółowo

C# 6.0 : księga przepisów / Jay Hilyard, Stephen Teilhet. Warszawa, Spis treści

C# 6.0 : księga przepisów / Jay Hilyard, Stephen Teilhet. Warszawa, Spis treści C# 6.0 : księga przepisów / Jay Hilyard, Stephen Teilhet. Warszawa, 2015 Spis treści Wstęp xi 1 Klasy i typy generyczne 1 1.0 Wprowadzenie 1 1.1 Tworzenie unii 3 1.2 Umożliwianie sortowania typu 6 1.3

Bardziej szczegółowo

C# 6.0 : kompletny przewodnik dla praktyków / Mark Michaelis, Eric Lippert. Gliwice, cop Spis treści

C# 6.0 : kompletny przewodnik dla praktyków / Mark Michaelis, Eric Lippert. Gliwice, cop Spis treści C# 6.0 : kompletny przewodnik dla praktyków / Mark Michaelis, Eric Lippert. Gliwice, cop. 2016 Spis treści Spis rysunków 11 Spis tabel 13 Przedmowa 15 Wprowadzenie 17 Podziękowania 27 O autorach 29 1 Wprowadzenie

Bardziej szczegółowo

SZYBKO ZROZUMIEĆ VISUAL BASIC 2012 Artur Niewiarowski -

SZYBKO ZROZUMIEĆ VISUAL BASIC 2012 Artur Niewiarowski - S t r o n a 2 SZYBKO ZROZUMIEĆ VISUAL BASIC 2012 Artur Niewiarowski - Copyright by Artur Niewiarowski 2013 ISBN: 978-83-937802-0-4 - Artur Niewiarowski Self-Publishing - All rights reserved. Wszelkie prawa

Bardziej szczegółowo

Programowanie dla początkujących w 24 godziny / Greg Perry, Dean Miller. Gliwice, cop Spis treści

Programowanie dla początkujących w 24 godziny / Greg Perry, Dean Miller. Gliwice, cop Spis treści Programowanie dla początkujących w 24 godziny / Greg Perry, Dean Miller. Gliwice, cop. 2017 Spis treści O autorach 11 Podziękowania 12 Wprowadzenie 13 CZĘŚĆ I ZACZNIJ PROGRAMOWAĆ JUŻ DZIŚ Godzina 1. Praktyczne

Bardziej szczegółowo

Wprowadzenie do programowania

Wprowadzenie do programowania do programowania ITA-104 Wersja 1 Warszawa, Wrzesień 2009 ITA-104 do programowania Informacje o kursie Zakres tematyczny kursu Opis kursu Kurs przeznaczony jest do prowadzenia przedmiotu do programowania

Bardziej szczegółowo

Podstawy programowania. Wprowadzenie

Podstawy programowania. Wprowadzenie Podstawy programowania Wprowadzenie Proces tworzenia programu Sformułowanie problemu funkcje programu zakres i postać danych postać i dokładność wyników Wybór / opracowanie metody rozwiązania znaleźć matematyczne

Bardziej szczegółowo

Zacznij Tu! Poznaj Microsoft 2012. Visual Basic. Michael Halvorson. Przekład: Joanna Zatorska

Zacznij Tu! Poznaj Microsoft 2012. Visual Basic. Michael Halvorson. Przekład: Joanna Zatorska Zacznij Tu! Poznaj Microsoft 2012 Visual Basic Michael Halvorson Przekład: Joanna Zatorska APN Promise, Warszawa 2013 Spis treści Wstęp...................................................................vii

Bardziej szczegółowo

Jeśli chcesz łatwo i szybko opanować podstawy C++, sięgnij po tę książkę.

Jeśli chcesz łatwo i szybko opanować podstawy C++, sięgnij po tę książkę. Języki C i C++ to bardzo uniwersalne platformy programistyczne o ogromnych możliwościach. Wykorzystywane są do tworzenia systemów operacyjnych i oprogramowania użytkowego. Dzięki niskiemu poziomowi abstrakcji

Bardziej szczegółowo

Programowanie obiektowe

Programowanie obiektowe Programowanie obiektowe Laboratorium 1. Wstęp do programowania w języku Java. Narzędzia 1. Aby móc tworzyć programy w języku Java, potrzebny jest zestaw narzędzi Java Development Kit, który można ściągnąć

Bardziej szczegółowo

Programista samouk : profesjonalny przewodnik do samodzielnej nauki kodowania / Cory Althoff. Gliwice, copyright Spis treści

Programista samouk : profesjonalny przewodnik do samodzielnej nauki kodowania / Cory Althoff. Gliwice, copyright Spis treści Programista samouk : profesjonalny przewodnik do samodzielnej nauki kodowania / Cory Althoff. Gliwice, copyright 2018 Spis treści Część I. Wprowadzenie do programowania 13 Rozdział 1. Wprowadzenie 15 Struktura

Bardziej szczegółowo

Programowanie obiektowe

Programowanie obiektowe Laboratorium z przedmiotu Programowanie obiektowe - zestaw 02 Cel zajęć. Celem zajęć jest zapoznanie z praktycznymi aspektami projektowania oraz implementacji klas i obiektów z wykorzystaniem dziedziczenia.

Bardziej szczegółowo

Podstawy programowania. Wykład Funkcje. Krzysztof Banaś Podstawy programowania 1

Podstawy programowania. Wykład Funkcje. Krzysztof Banaś Podstawy programowania 1 Podstawy programowania. Wykład Funkcje Krzysztof Banaś Podstawy programowania 1 Programowanie proceduralne Pojęcie procedury (funkcji) programowanie proceduralne realizacja określonego zadania specyfikacja

Bardziej szczegółowo

Programowanie MorphX Ax

Programowanie MorphX Ax Administrowanie Czym jest system ERP? do systemu Dynamics Ax Obsługa systemu Dynamics Ax Wyszukiwanie informacji, filtrowanie, sortowanie rekordów IntelliMorph : ukrywanie i pokazywanie ukrytych kolumn

Bardziej szczegółowo

Rok akademicki: 2012/2013 Kod: ZIE-1-306-s Punkty ECTS: 3. Poziom studiów: Studia I stopnia Forma i tryb studiów: -

Rok akademicki: 2012/2013 Kod: ZIE-1-306-s Punkty ECTS: 3. Poziom studiów: Studia I stopnia Forma i tryb studiów: - Nazwa modułu: Programowanie obiektowe Rok akademicki: 2012/2013 Kod: ZIE-1-306-s Punkty ECTS: 3 Wydział: Zarządzania Kierunek: Informatyka i Ekonometria Specjalność: - Poziom studiów: Studia I stopnia

Bardziej szczegółowo

PLAN WYNIKOWY PROGRAMOWANIE APLIKACJI INTERNETOWYCH. KL IV TI 6 godziny tygodniowo (6x15 tygodni =90 godzin ),

PLAN WYNIKOWY PROGRAMOWANIE APLIKACJI INTERNETOWYCH. KL IV TI 6 godziny tygodniowo (6x15 tygodni =90 godzin ), PLAN WYNIKOWY PROGRAMOWANIE APLIKACJI INTERNETOWYCH KL IV TI 6 godziny tygodniowo (6x15 tygodni =90 godzin ), Program 351203 Opracowanie: Grzegorz Majda Tematyka zajęć 2. Przygotowanie środowiska pracy

Bardziej szczegółowo

Programowanie obiektowe

Programowanie obiektowe Laboratorium z przedmiotu - zestaw 02 Cel zajęć. Celem zajęć jest zapoznanie z praktycznymi aspektami projektowania oraz implementacji klas i obiektów z wykorzystaniem dziedziczenia. Wprowadzenie teoretyczne.

Bardziej szczegółowo

Podstawy programowania skrót z wykładów:

Podstawy programowania skrót z wykładów: Podstawy programowania skrót z wykładów: // komentarz jednowierszowy. /* */ komentarz wielowierszowy. # include dyrektywa preprocesora, załączająca biblioteki (pliki nagłówkowe). using namespace

Bardziej szczegółowo

Bezpieczenstwo aplikacji

Bezpieczenstwo aplikacji Języki Programowania na Platformie.NET (część 2) http://www.kaims.pl/ goluch/ goluch@eti.pg.gda.pl Bezpieczeństwo ogólne koncepcje sandboxing zbiór praw jest określany poprzez evidence prawa (permissions)

Bardziej szczegółowo

1 Podstawy c++ w pigułce.

1 Podstawy c++ w pigułce. 1 Podstawy c++ w pigułce. 1.1 Struktura dokumentu. Kod programu c++ jest zwykłym tekstem napisanym w dowolnym edytorze. Plikowi takiemu nadaje się zwykle rozszerzenie.cpp i kompiluje za pomocą kompilatora,

Bardziej szczegółowo

Laboratorium Systemów Operacyjnych

Laboratorium Systemów Operacyjnych Laboratorium Systemów Operacyjnych Użytkownicy, Grupy, Prawa Tworzenie kont użytkowników Lokalne konto pozwala użytkownikowi na uzyskanie dostępu do zasobów lokalnego komputera. Konto domenowe pozwala

Bardziej szczegółowo

Wykonać Ćwiczenie: Active Directory, konfiguracja Podstawowa

Wykonać Ćwiczenie: Active Directory, konfiguracja Podstawowa Wykonać Ćwiczenie: Active Directory, konfiguracja Podstawowa Instalacja roli kontrolera domeny, Aby zainstalować rolę kontrolera domeny, należy uruchomić Zarządzenie tym serwerem, po czym wybrać przycisk

Bardziej szczegółowo

Część I Tworzenie baz danych SQL Server na potrzeby przechowywania danych

Część I Tworzenie baz danych SQL Server na potrzeby przechowywania danych Spis treści Wprowadzenie... ix Organizacja ksiąŝki... ix Od czego zacząć?... x Konwencje przyjęte w ksiąŝce... x Wymagania systemowe... xi Przykłady kodu... xii Konfiguracja SQL Server 2005 Express Edition...

Bardziej szczegółowo

TOPIT Załącznik nr 3 Programowanie aplikacji internetowych

TOPIT Załącznik nr 3 Programowanie aplikacji internetowych Szkolenie przeznaczone jest dla osób chcących poszerzyć swoje umiejętności o tworzenie rozwiązań internetowych w PHP. Zajęcia zostały przygotowane w taki sposób, aby po ich ukończeniu można było rozpocząć

Bardziej szczegółowo

Podczas dziedziczenia obiekt klasy pochodnej może być wskazywany przez wskaźnik typu klasy bazowej.

Podczas dziedziczenia obiekt klasy pochodnej może być wskazywany przez wskaźnik typu klasy bazowej. Polimorfizm jest filarem programowania obiektowego, nie tylko jeżeli chodzi o język C++. Daje on programiście dużą elastyczność podczas pisania programu. Polimorfizm jest ściśle związany z metodami wirtualnymi.

Bardziej szczegółowo

Wykład 8: klasy cz. 4

Wykład 8: klasy cz. 4 Programowanie obiektowe Wykład 8: klasy cz. 4 Dynamiczne tworzenie obiektów klas Składniki statyczne klas Konstruktor i destruktory c.d. 1 dr Artur Bartoszewski - Programowanie obiektowe, sem. 1I- WYKŁAD

Bardziej szczegółowo

java.util.* :Kolekcje Tomasz Borzyszkowski

java.util.* :Kolekcje Tomasz Borzyszkowski java.util.* :Kolekcje Tomasz Borzyszkowski Wstęp Kolekcje w Java dają programiście pewien standardowy sposób radzenia sobie z przetwarzaniem grup obiektów. Implementacja kolekcji w Java składa się z następujących

Bardziej szczegółowo

Java w 21 dni / Rogers Cadenhead. Gliwice, cop Spis treści. O autorze 11. Wprowadzenie 13 TYDZIEŃ I JĘZYK JAVA

Java w 21 dni / Rogers Cadenhead. Gliwice, cop Spis treści. O autorze 11. Wprowadzenie 13 TYDZIEŃ I JĘZYK JAVA Java w 21 dni / Rogers Cadenhead. Gliwice, cop. 2016 Spis treści O autorze 11 Wprowadzenie 13 TYDZIEŃ I JĘZYK JAVA Dzień 1. Rozpoczynamy przygodę z Javą 21 Język Java 21 Programowanie obiektowe 24 Obiekty

Bardziej szczegółowo

Informacje ogólne. Karol Trybulec p-programowanie.pl 1. 2 // cialo klasy. class osoba { string imie; string nazwisko; int wiek; int wzrost;

Informacje ogólne. Karol Trybulec p-programowanie.pl 1. 2 // cialo klasy. class osoba { string imie; string nazwisko; int wiek; int wzrost; Klasy w C++ są bardzo ważnym narzędziem w rękach programisty. Klasy są fundamentem programowania obiektowego. Z pomocą klas będziesz mógł tworzyć lepszy kod, a co najważniejsze będzie on bardzo dobrze

Bardziej szczegółowo

Microsoft Official Academic Course. Linda Silva. Microsoft Word 2010. Egzamin 77-881

Microsoft Official Academic Course. Linda Silva. Microsoft Word 2010. Egzamin 77-881 Microsoft Official Academic Course Linda Silva Microsoft Word 2010 Egzamin 77-881 APN Promise Warszawa 2012 Microsoft Official Academic Course: Microsoft Word 2010 Egzamin 77-881 Original English language

Bardziej szczegółowo

Podstawy programowania. Wykład: 9. Łańcuchy znaków. dr Artur Bartoszewski -Podstawy programowania, sem 1 - WYKŁAD

Podstawy programowania. Wykład: 9. Łańcuchy znaków. dr Artur Bartoszewski -Podstawy programowania, sem 1 - WYKŁAD Podstawy programowania Wykład: 9 Łańcuchy znaków 1 dr Artur Bartoszewski -Podstawy programowania, sem 1 - WYKŁAD Tablica znaków w językach C i C++ (oraz pochodnych) łańcuch znaków przechowywany jest jako

Bardziej szczegółowo

Część 3 - Konfiguracja

Część 3 - Konfiguracja Spis treści Część 3 - Konfiguracja... 3 Konfiguracja kont użytkowników... 4 Konfiguracja pól dodatkowych... 5 Konfiguracja kont email... 6 Konfiguracja szablonów dokumentów... 8 Konfiguracja czynności

Bardziej szczegółowo

76.Struktura oprogramowania rozproszonego.

76.Struktura oprogramowania rozproszonego. 76.Struktura oprogramowania rozproszonego. NajwaŜniejsze aspekty obiektowego programowania rozproszonego to: Współdziałanie (interoperability) modułów programowych na róŝnych maszynach. Wielokrotne wykorzystanie

Bardziej szczegółowo

Wykład 3 Składnia języka C# (cz. 2)

Wykład 3 Składnia języka C# (cz. 2) Wizualne systemy programowania Wykład 3 Składnia języka C# (cz. 2) 1 dr Artur Bartoszewski -Wizualne systemy programowania, sem. III- WYKŁAD Wizualne systemy programowania Metody 2 Metody W C# nie jest

Bardziej szczegółowo

Programowanie w języku Swift : Big Nerd Ranch guide / Matthew Mathias, John Gallagher. Gliwice, cop Spis treści

Programowanie w języku Swift : Big Nerd Ranch guide / Matthew Mathias, John Gallagher. Gliwice, cop Spis treści Programowanie w języku Swift : Big Nerd Ranch guide / Matthew Mathias, John Gallagher. Gliwice, cop. 2017 Spis treści Wprowadzenie 13 Poznawanie języka Swift 13 Dokąd zmierza Objective-C? 13 Przygotowania

Bardziej szczegółowo

Myśl w języku Python! : nauka programowania / Allen B. Downey. Gliwice, cop Spis treści

Myśl w języku Python! : nauka programowania / Allen B. Downey. Gliwice, cop Spis treści Myśl w języku Python! : nauka programowania / Allen B. Downey. Gliwice, cop. 2017 Spis treści Przedmowa 11 1. Jak w programie 21 Czym jest program? 21 Uruchamianie interpretera języka Python 22 Pierwszy

Bardziej szczegółowo

Backend Administratora

Backend Administratora Backend Administratora mgr Tomasz Xięski, Instytut Informatyki, Uniwersytet Śląski Katowice, 2011 W tym celu korzystając z konsoli wydajemy polecenie: symfony generate:app backend Wówczas zostanie stworzona

Bardziej szczegółowo

Wykład 5: Klasy cz. 3

Wykład 5: Klasy cz. 3 Programowanie obiektowe Wykład 5: cz. 3 1 dr Artur Bartoszewski - Programowanie obiektowe, sem. 1I- WYKŁAD - podstawy Konstruktor i destruktor (część I) 2 Konstruktor i destruktor KONSTRUKTOR Dla przykładu

Bardziej szczegółowo

DESlock+ szybki start

DESlock+ szybki start DESlock+ szybki start Wersja centralnie zarządzana Wersja bez centralnej administracji standalone WAŻNE! Pamiętaj, że jeśli chcesz korzystać z centralnego zarządzania koniecznie zacznij od instalacji serwera

Bardziej szczegółowo

Część I Dostęp do danych oraz moŝliwości programowe (silnik bazy danych)

Część I Dostęp do danych oraz moŝliwości programowe (silnik bazy danych) Spis treści Wstęp... xi Część I Dostęp do danych oraz moŝliwości programowe (silnik bazy danych) 1 Program SQL Server Management Studio oraz język Transact SQL... 3 Omówienie programu SQL Server Management

Bardziej szczegółowo

Java - tablice, konstruktory, dziedziczenie i hermetyzacja

Java - tablice, konstruktory, dziedziczenie i hermetyzacja Java - tablice, konstruktory, dziedziczenie i hermetyzacja Programowanie w językach wysokiego poziomu mgr inż. Anna Wawszczak PLAN WYKŁADU zmienne tablicowe konstruktory klas dziedziczenie hermetyzacja

Bardziej szczegółowo

Jarosław Kuchta Administrowanie Systemami Komputerowymi. Internetowe Usługi Informacyjne

Jarosław Kuchta Administrowanie Systemami Komputerowymi. Internetowe Usługi Informacyjne Jarosław Kuchta Internetowe Usługi Informacyjne Komponenty IIS HTTP.SYS serwer HTTP zarządzanie połączeniami TCP/IP buforowanie odpowiedzi obsługa QoS (Quality of Service) obsługa plików dziennika IIS

Bardziej szczegółowo

Baza danych sql. 1. Wprowadzenie

Baza danych sql. 1. Wprowadzenie Baza danych sql 1. Wprowadzenie Do tej pory operowaliście na listach. W tej instrukcji pokazane zostanie jak stworzyć bazę danych. W zadaniu skorzystamy z edytora graficznego struktury bazy danych, który

Bardziej szczegółowo

Wykład 2 Składnia języka C# (cz. 1)

Wykład 2 Składnia języka C# (cz. 1) Wizualne systemy programowania Wykład 2 Składnia języka C# (cz. 1) 1 dr Artur Bartoszewski -Wizualne systemy programowania, sem. III- WYKŁAD Wizualne systemy programowania Budowa projektu 2 Struktura programu

Bardziej szczegółowo

PHP: bloki kodu, tablice, obiekty i formularze

PHP: bloki kodu, tablice, obiekty i formularze 1 PHP: bloki kodu, tablice, obiekty i formularze SYSTEMY SIECIOWE Michał Simiński 2 Bloki kodu Blok if-else Switch Pętle Funkcje Blok if-else 3 W PHP blok if i blok if-else wyglądają tak samo i funkcjonują

Bardziej szczegółowo

Być może jesteś doświadczonym programistą, biegle programujesz w Javie,

Być może jesteś doświadczonym programistą, biegle programujesz w Javie, Kompendium PHP 01 Być może jesteś doświadczonym programistą, biegle programujesz w Javie, C++, Pythonie lub jakimś innym języku programowania, których jak myślę, powstało już tyle, że chyba nie ma osoby,

Bardziej szczegółowo

Programowanie współbieżne i rozproszone

Programowanie współbieżne i rozproszone Programowanie współbieżne i rozproszone WYKŁAD 11 dr inż. CORBA CORBA (Common Object Request Broker Architecture) standard programowania rozproszonego zaproponowany przez OMG (Object Management Group)

Bardziej szczegółowo

Kod doskonały : jak tworzyć oprogramowanie pozbawione błędów / Steve McConnell. Gliwice, cop Spis treści. Wstęp 15.

Kod doskonały : jak tworzyć oprogramowanie pozbawione błędów / Steve McConnell. Gliwice, cop Spis treści. Wstęp 15. Kod doskonały : jak tworzyć oprogramowanie pozbawione błędów / Steve McConnell. Gliwice, cop. 2017 Spis treści Wstęp 15 Podziękowania 23 Listy kontrolne 25 Tabele 27 Rysunki 29 Część I Proces budowy oprogramowania

Bardziej szczegółowo

System kontroli wersji - wprowadzenie. Rzeszów,2 XII 2010

System kontroli wersji - wprowadzenie. Rzeszów,2 XII 2010 System kontroli wersji - wprowadzenie Rzeszów,2 XII 2010 System kontroli wersji System kontroli wersji (ang. version/revision control system) służy do śledzenia zmian głównie w kodzie źródłowym oraz pomocy

Bardziej szczegółowo

1 Implementowanie i konfigurowanie infrastruktury wdraŝania systemu Windows... 1

1 Implementowanie i konfigurowanie infrastruktury wdraŝania systemu Windows... 1 Spis treści Wstęp... xi Wymagania sprzętowe (Virtual PC)... xi Wymagania sprzętowe (fizyczne)... xii Wymagania programowe... xiii Instrukcje instalowania ćwiczeń... xiii Faza 1: Tworzenie maszyn wirtualnych...

Bardziej szczegółowo

Zadanie1: Odszukaj w serwisie internetowym Wikipedii informacje na temat protokołu http.

Zadanie1: Odszukaj w serwisie internetowym Wikipedii informacje na temat protokołu http. T: Konfiguracja usługi HTTP w systemie Windows. Zadanie1: Odszukaj w serwisie internetowym Wikipedii informacje na temat protokołu http. HTTP (ang. Hypertext Transfer Protocol) protokół transferu plików

Bardziej szczegółowo

Dokument opisuje sposób postępowania prowadzący do wysłania deklaracji VAT, PIT lub CIT drogą elektroniczną za pomocą funkcji systemu ADA modułu FK.

Dokument opisuje sposób postępowania prowadzący do wysłania deklaracji VAT, PIT lub CIT drogą elektroniczną za pomocą funkcji systemu ADA modułu FK. FK - EDeklaracje Dokument opisuje sposób postępowania prowadzący do wysłania deklaracji VAT, PIT lub CIT drogą elektroniczną za pomocą funkcji systemu ADA modułu FK. W założeniu przyjęto, iż użytkownik

Bardziej szczegółowo

Leonard G. Lobel Eric D. Boyd. Azure SQL Database Krok po kroku. Microsoft. Przekład: Marek Włodarz. APN Promise, Warszawa 2014

Leonard G. Lobel Eric D. Boyd. Azure SQL Database Krok po kroku. Microsoft. Przekład: Marek Włodarz. APN Promise, Warszawa 2014 Leonard G. Lobel Eric D. Boyd Microsoft TM Azure SQL Database Krok po kroku Przekład: Marek Włodarz APN Promise, Warszawa 2014 Spis treści Wprowadzenie........................................................

Bardziej szczegółowo

XQTav - reprezentacja diagramów przepływu prac w formacie SCUFL przy pomocy XQuery

XQTav - reprezentacja diagramów przepływu prac w formacie SCUFL przy pomocy XQuery http://xqtav.sourceforge.net XQTav - reprezentacja diagramów przepływu prac w formacie SCUFL przy pomocy XQuery dr hab. Jerzy Tyszkiewicz dr Andrzej Kierzek mgr Jacek Sroka Grzegorz Kaczor praca mgr pod

Bardziej szczegółowo

Wskaźniki a tablice Wskaźniki i tablice są ze sobą w języku C++ ściśle związane. Aby się o tym przekonać wykonajmy cwiczenie.

Wskaźniki a tablice Wskaźniki i tablice są ze sobą w języku C++ ściśle związane. Aby się o tym przekonać wykonajmy cwiczenie. Część XXII C++ w Wskaźniki a tablice Wskaźniki i tablice są ze sobą w języku C++ ściśle związane. Aby się o tym przekonać wykonajmy cwiczenie. Ćwiczenie 1 1. Utwórz nowy projekt w Dev C++ i zapisz go na

Bardziej szczegółowo

Część I Rozpoczęcie pracy z usługami Reporting Services

Część I Rozpoczęcie pracy z usługami Reporting Services Spis treści Podziękowania... xi Wprowadzenie... xiii Część I Rozpoczęcie pracy z usługami Reporting Services 1 Wprowadzenie do usług Reporting Services... 3 Platforma raportowania... 3 Cykl życia raportu...

Bardziej szczegółowo

Spis treści. oraz Microsoft Visual Studio Wstęp... xiii. Część I Wprowadzenie do języka Microsoft Visual C# 1 Wprowadzenie do języka C#...

Spis treści. oraz Microsoft Visual Studio Wstęp... xiii. Część I Wprowadzenie do języka Microsoft Visual C# 1 Wprowadzenie do języka C#... Spis treści Wstęp... xiii Część I Wprowadzenie do języka Microsoft Visual C# oraz Microsoft Visual Studio 2010 1 Wprowadzenie do języka C#... 3 Rozpoczynamy programowanie przy użyciu środowiska Visual

Bardziej szczegółowo

Wprowadzenie do projektu QualitySpy

Wprowadzenie do projektu QualitySpy Wprowadzenie do projektu QualitySpy Na podstawie instrukcji implementacji prostej funkcjonalności. 1. Wstęp Celem tego poradnika jest wprowadzić programistę do projektu QualitySpy. Będziemy implementować

Bardziej szczegółowo

Baza danych sql. 1. Wprowadzenie. 2. Repozytaria generyczne

Baza danych sql. 1. Wprowadzenie. 2. Repozytaria generyczne Baza danych sql 1. Wprowadzenie Do tej pory operowaliście na listach. W tej instrukcji pokazane zostanie jak stworzyć bazę danych. W zadaniu skorzystamy z możliwości utworzenia struktury bazy danych z

Bardziej szczegółowo

Efektywne zarządzanie czasem

Efektywne zarządzanie czasem Efektywne zarządzanie czasem Jak wykorzystać Microsoft Outlook do zorganizowania pracy i życia osobistego Lothar Seiwert Holger Woeltje przekład Marek Włodarz APN Promise, Warszawa 2012 Efektywne zarządzanie

Bardziej szczegółowo

Microsoft Excel 2010 Analiza i modelowanie danych biznesowych

Microsoft Excel 2010 Analiza i modelowanie danych biznesowych Microsoft Excel 2010 Analiza i modelowanie danych biznesowych Wayne L. Winston Przekład: Janusz Machowski APN Promise Warszawa 2011 Microsoft Excel 2010: Analiza i modelowanie danych biznesowych 2011 APN

Bardziej szczegółowo

Od uczestników szkolenia wymagana jest umiejętność programowania w języku C oraz podstawowa znajomość obsługi systemu Windows.

Od uczestników szkolenia wymagana jest umiejętność programowania w języku C oraz podstawowa znajomość obsługi systemu Windows. Kod szkolenia: Tytuł szkolenia: PS/WIN Programowanie systemowe w Windows Dni: 5 Opis: Adresaci szkolenia Szkolenie adresowane jest do programistów tworzących aplikacje w systemach z rodziny Microsoft Windows,

Bardziej szczegółowo

Podstawy Programowania Obiektowego

Podstawy Programowania Obiektowego Podstawy Programowania Obiektowego Wprowadzenie do programowania obiektowego. Pojęcie struktury i klasy. Spotkanie 03 Dr inż. Dariusz JĘDRZEJCZYK Tematyka wykładu Idea programowania obiektowego Definicja

Bardziej szczegółowo

Microsoft Visual C : praktyczne przykłady / Mariusz Owczarek. Gliwice, cop Spis treści

Microsoft Visual C : praktyczne przykłady / Mariusz Owczarek. Gliwice, cop Spis treści Microsoft Visual C++ 2008 : praktyczne przykłady / Mariusz Owczarek. Gliwice, cop. 2010 Spis treści Co znajdziesz w tej książce? 9 Rozdział 1. Podstawy środowiska Visual C++ 2008 11 Język C++ a.net Framework

Bardziej szczegółowo

Instrukcja konfigurowania poczty Exchange dla klienta pocztowego użytkowanego poza siecią uczelnianą SGH.

Instrukcja konfigurowania poczty Exchange dla klienta pocztowego użytkowanego poza siecią uczelnianą SGH. Instrukcja konfigurowania poczty Exchange dla klienta pocztowego użytkowanego poza siecią uczelnianą SGH. Spis treści 1. Konfiguracja poczty Exchange dla klienta pocztowego Outlook 2007 protokół Exchange

Bardziej szczegółowo

Wprowadzenie. Organizacja pracy i środowisko programistyczne. Mirosław Ochodek

Wprowadzenie. Organizacja pracy i środowisko programistyczne. Mirosław Ochodek Wprowadzenie Organizacja pracy i środowisko programistyczne Mirosław Ochodek Miroslaw.Ochodek@pwsz.pila.pl Miroslaw.Ochodek@cs.put.poznan.pl Dane kontaktowe Mirosław Ochodek E-mail: Miroslaw.Ochodek@pwsz.pila.pl

Bardziej szczegółowo

UML a kod w C++ i Javie. Przypadki użycia. Diagramy klas. Klasy użytkowników i wykorzystywane funkcje. Związki pomiędzy przypadkami.

UML a kod w C++ i Javie. Przypadki użycia. Diagramy klas. Klasy użytkowników i wykorzystywane funkcje. Związki pomiędzy przypadkami. UML a kod w C++ i Javie Projektowanie oprogramowania Dokumentowanie oprogramowania Diagramy przypadków użycia Przewoznik Zarzadzanie pojazdami Optymalizacja Uzytkownik Wydawanie opinii Zarzadzanie uzytkownikami

Bardziej szczegółowo

Windows W celu dostępu do i konfiguracji firewall idź do Panelu sterowania -> System i zabezpieczenia -> Zapora systemu Windows.

Windows W celu dostępu do i konfiguracji firewall idź do Panelu sterowania -> System i zabezpieczenia -> Zapora systemu Windows. Bezpieczeństwo Systemów Informatycznych Firewall (Zapora systemu) Firewall (zapora systemu) jest ważnym elementem bezpieczeństwa współczesnych systemów komputerowych. Jego główną rolą jest kontrola ruchu

Bardziej szczegółowo

Instrukcje dotyczące systemu Windows w przypadku drukarki podłączonej lokalnie

Instrukcje dotyczące systemu Windows w przypadku drukarki podłączonej lokalnie Strona 1 z 6 Połączenia Instrukcje dotyczące systemu Windows w przypadku drukarki podłączonej lokalnie Uwaga: Przy instalowaniu drukarki podłączonej lokalnie, jeśli dysk CD-ROM Oprogramowanie i dokumentacja

Bardziej szczegółowo

Instrukcja laboratoryjna

Instrukcja laboratoryjna Zaawansowane techniki obiektowe 2016/17 Instrukcja laboratoryjna Testy funkcjonalne Prowadzący: Tomasz Goluch Wersja: 1.0 Testowanie aplikacji z bazą danych Większość współczesnych aplikacji korzysta z

Bardziej szczegółowo

Obsługa poczty elektronicznej w domenie emeritus.ue.poznan.pl

Obsługa poczty elektronicznej w domenie emeritus.ue.poznan.pl Obsługa poczty elektronicznej w domenie emeritus.ue.poznan.pl Centrum Informatyki http://ci.ue.poznan.pl helpdesk@ue.poznan.pl al. Niepodległości 10, 61-875 Poznań tel. + 48 61 856 90 00 NIP: 777-00-05-497

Bardziej szczegółowo

Obiekt klasy jest definiowany poprzez jej składniki. Składnikami są różne zmienne oraz funkcje. Składniki opisują rzeczywisty stan obiektu.

Obiekt klasy jest definiowany poprzez jej składniki. Składnikami są różne zmienne oraz funkcje. Składniki opisują rzeczywisty stan obiektu. Zrozumienie funkcji danych statycznych jest podstawą programowania obiektowego. W niniejszym artykule opiszę zasadę tworzenia klas statycznych w C#. Oprócz tego dowiesz się czym są statyczne pola i metody

Bardziej szczegółowo

asix Autoryzacja dostępu do zasobów WWW systemu asix (na przykładzie systemu operacyjnego Windows 2008)

asix Autoryzacja dostępu do zasobów WWW systemu asix (na przykładzie systemu operacyjnego Windows 2008) NIEZAWODNE ROZWIĄZANIA SYSTEMÓW AUTOMATYKI asix (na przykładzie systemu operacyjnego Windows 2008) Pomoc techniczna Dok. Nr PLP0018 Wersja: 2011-08-26 ASKOM i asix to zastrzeżony znak firmy ASKOM Sp. z

Bardziej szczegółowo

Curtis D. Frye. Microsoft Excel Krok po kroku. Przekład: Leszek Biolik

Curtis D. Frye. Microsoft Excel Krok po kroku. Przekład: Leszek Biolik Curtis D. Frye Microsoft Excel 2013 Krok po kroku Przekład: Leszek Biolik APN Promise, Warszawa 2013 Spis treści Wprowadzenie............................................................. xi 1 Rozpoczynamy

Bardziej szczegółowo

Windows Serwer 2008 R2. Moduł 8. Mechanizmy kopii zapasowych

Windows Serwer 2008 R2. Moduł 8. Mechanizmy kopii zapasowych Windows Serwer 2008 R2 Moduł 8. Mechanizmy kopii zapasowych Co nowego w narzędziu Kopia zapasowa? 1. Większa elastyczność w zakresie możliwości wykonywania kopii zapasowych 2. Automatyczne zarządzanie

Bardziej szczegółowo

Instrukcja konfiguracji funkcji skanowania

Instrukcja konfiguracji funkcji skanowania Instrukcja konfiguracji funkcji skanowania WorkCentre M123/M128 WorkCentre Pro 123/128 701P42171_PL 2004. Wszystkie prawa zastrzeżone. Rozpowszechnianie bez zezwolenia przedstawionych materiałów i informacji

Bardziej szczegółowo

ROZSZERZANIE MOŻLIWOŚCI...

ROZSZERZANIE MOŻLIWOŚCI... SPIS TREŚCI: Od Autora... 11 ROZSZERZANIE MOŻLIWOŚCI... 13 PROGRAMY PREFERENCYJNE... 15 Czcionki systemowe... 15 Tła okien... 18 Tryb wyświetlania... 22 Zegar i data systemowa... 24 Urządzenia wejścia

Bardziej szczegółowo

Microsoft Office 2016 Krok po kroku

Microsoft Office 2016 Krok po kroku Joan Lambert Curtis Frye Microsoft Office 2016 Krok po kroku Przekład: Leszek Biolik, Krzysztof Kapustka, Marek Włodarz APN Promise, Warszawa 2016 Spis treści Wprowadzenie.........................................................ix

Bardziej szczegółowo

Szablony funkcji i klas (templates)

Szablony funkcji i klas (templates) Instrukcja laboratoryjna nr 3 Programowanie w języku C 2 (C++ poziom zaawansowany) Szablony funkcji i klas (templates) dr inż. Jacek Wilk-Jakubowski mgr inż. Maciej Lasota dr inż. Tomasz Kaczmarek Wstęp

Bardziej szczegółowo

Język C : programowanie dla początkujących : przewodnik dla adeptów programowania / Greg Perry, Dean Miller. Gliwice, cop

Język C : programowanie dla początkujących : przewodnik dla adeptów programowania / Greg Perry, Dean Miller. Gliwice, cop Język C : programowanie dla początkujących : przewodnik dla adeptów programowania / Greg Perry, Dean Miller. Gliwice, cop. 2016 Spis treści Wprowadzenie 11 Adresaci książki 12 Co wyróżnia tę książkę na

Bardziej szczegółowo

Budowa aplikacji ASP.NET z wykorzystaniem wzorca MVC

Budowa aplikacji ASP.NET z wykorzystaniem wzorca MVC Akademia MetaPack Uniwersytet Zielonogórski Budowa aplikacji ASP.NET z wykorzystaniem wzorca MVC Krzysztof Blacha Microsoft Certified Professional Budowa aplikacji ASP.NET z wykorzystaniem wzorca MVC Agenda:

Bardziej szczegółowo

Samsung Universal Print Driver Podręcznik użytkownika

Samsung Universal Print Driver Podręcznik użytkownika Samsung Universal Print Driver Podręcznik użytkownika wyobraź sobie możliwości Copyright 2009 Samsung Electronics Co., Ltd. Wszelkie prawa zastrzeżone. Ten podręcznik administratora dostarczono tylko w

Bardziej szczegółowo

Tomasz Greszata - Koszalin

Tomasz Greszata - Koszalin T: Konfiguracja usługi HTTP w systemie Windows. Zadanie1: Odszukaj w serwisie internetowym Wikipedii informacje na temat protokołów HTTP oraz HTTPS i oprogramowania IIS (ang. Internet Information Services).

Bardziej szczegółowo

Internetowy serwis Era mail Aplikacja sieci Web

Internetowy serwis Era mail Aplikacja sieci Web Internetowy serwis Era mail Aplikacja sieci Web (www.login.eramail.pl) INSTRUKCJA OBSŁUGI Spis treści Internetowy serwis Era mail dostępny przez komputer z podłączeniem do Internetu (aplikacja sieci Web)

Bardziej szczegółowo

Memeo Instant Backup Podręcznik Szybkiego Startu

Memeo Instant Backup Podręcznik Szybkiego Startu Wprowadzenie Memeo Instant Backup pozwala w łatwy sposób chronić dane przed zagrożeniami cyfrowego świata. Aplikacja regularnie i automatycznie tworzy kopie zapasowe ważnych plików znajdujących się na

Bardziej szczegółowo

Techniki programowania INP001002Wl rok akademicki 2018/19 semestr letni. Wykład 3. Karol Tarnowski A-1 p.

Techniki programowania INP001002Wl rok akademicki 2018/19 semestr letni. Wykład 3. Karol Tarnowski A-1 p. Techniki programowania INP001002Wl rok akademicki 2018/19 semestr letni Wykład 3 Karol Tarnowski karol.tarnowski@pwr.edu.pl A-1 p. 411B Plan prezentacji Abstrakcja funkcyjna Struktury Klasy hermetyzacja

Bardziej szczegółowo

Zaawansowane aplikacje internetowe - laboratorium

Zaawansowane aplikacje internetowe - laboratorium Zaawansowane aplikacje internetowe - laboratorium Web Services (część 3). Do wykonania ćwiczeń potrzebne jest zintegrowane środowisko programistyczne Microsoft Visual Studio 2005. Ponadto wymagany jest

Bardziej szczegółowo

11. Autoryzacja użytkowników

11. Autoryzacja użytkowników 11. Autoryzacja użytkowników Rozwiązanie NETASQ UTM pozwala na wykorzystanie trzech typów baz użytkowników: Zewnętrzna baza zgodna z LDAP OpenLDAP, Novell edirectory; Microsoft Active Direcotry; Wewnętrzna

Bardziej szczegółowo

Analiza i projektowanie oprogramowania. Analiza i projektowanie oprogramowania 1/32

Analiza i projektowanie oprogramowania. Analiza i projektowanie oprogramowania 1/32 Analiza i projektowanie oprogramowania Analiza i projektowanie oprogramowania 1/32 Analiza i projektowanie oprogramowania 2/32 Cel analizy Celem fazy określania wymagań jest udzielenie odpowiedzi na pytanie:

Bardziej szczegółowo

Programowanie Strukturalne i Obiektowe Słownik podstawowych pojęć 1 z 5 Opracował Jan T. Biernat

Programowanie Strukturalne i Obiektowe Słownik podstawowych pojęć 1 z 5 Opracował Jan T. Biernat Programowanie Strukturalne i Obiektowe Słownik podstawowych pojęć 1 z 5 Program, to lista poleceń zapisana w jednym języku programowania zgodnie z obowiązującymi w nim zasadami. Celem programu jest przetwarzanie

Bardziej szczegółowo

znajdowały się różne instrukcje) to tak naprawdę definicja funkcji main.

znajdowały się różne instrukcje) to tak naprawdę definicja funkcji main. Część XVI C++ Funkcje Jeśli nasz program rozrósł się już do kilkudziesięciu linijek, warto pomyśleć o jego podziale na mniejsze części. Poznajmy więc funkcje. Szybko się przekonamy, że funkcja to bardzo

Bardziej szczegółowo

Tworzenie i wykorzystanie usług sieciowych

Tworzenie i wykorzystanie usług sieciowych Ćwiczenie 14 Temat: Tworzenie i wykorzystanie usług sieciowych Cel ćwiczenia: W trakcie ćwiczenia student zapozna się z procedurą tworzenia usługi sieciowej w technologii ASP.NET oraz nauczy się tworzyć

Bardziej szczegółowo

Wprowadzenie (17) Część I. Makra w Excelu - podstawy (23)

Wprowadzenie (17) Część I. Makra w Excelu - podstawy (23) Wprowadzenie (17) Omówione zagadnienia (18) Co trzeba wiedzieć? (18) Co trzeba mieć? (18) Układ książki (18) o Część I. Makra w Excelu - podstawy (19) o Część II. Praca ze skoroszytami (19) o Część III.

Bardziej szczegółowo

Ed Wilson. Windows PowerShell Krok po kroku 3.0. Przekład: Marek Włodarz

Ed Wilson. Windows PowerShell Krok po kroku 3.0. Przekład: Marek Włodarz Ed Wilson Windows PowerShell Krok po kroku 3.0 Przekład: Marek Włodarz APN Promise, Warszawa 2013 Spis treści Przedmowa....xi Wprowadzenie....xiii 1 Przegląd cech Windows PowerShell 3.0.... 1 Istota Windows

Bardziej szczegółowo

Przesłanki powstania książki... xvi Dla kogo przeznaczona jest ta książka?... xvi Co znajdziemy wewnątrz książki?... xvii

Przesłanki powstania książki... xvi Dla kogo przeznaczona jest ta książka?... xvi Co znajdziemy wewnątrz książki?... xvii Przedmowa...ix Podziękowania....xi Wprowadzenie.... xv Przesłanki powstania książki... xvi Dla kogo przeznaczona jest ta książka?... xvi Co znajdziemy wewnątrz książki?... xvii Część pierwsza: Modele wykonywania

Bardziej szczegółowo

Programowanie obiektowe

Programowanie obiektowe Laboratorium z przedmiotu Programowanie obiektowe - zestaw 03 Cel zajęć. Celem zajęć jest zapoznanie z praktycznymi aspektami projektowania oraz implementacji klas abstrakcyjnych i interfejsów. Wprowadzenie

Bardziej szczegółowo

Microsoft Visual C# 2012 Krok po kroku

Microsoft Visual C# 2012 Krok po kroku John Sharp Microsoft Visual C# 2012 Krok po kroku Przekład: Janusz Machowski, Krzysztof Szkudlarek APN Promise, Warszawa 2013 Spis treści Wstęp..................................................................

Bardziej szczegółowo

Laboratorium - Obserwacja procesu tłumaczenia nazw DNS

Laboratorium - Obserwacja procesu tłumaczenia nazw DNS Laboratorium - Obserwacja procesu tłumaczenia nazw DNS Cele Część 1: Obserwacja konwersji DNS nazwy URL na adres IP. Część 2: Obserwacja procesu przeszukiwania nazw DNS, przy pomocy polecenia Nslookup

Bardziej szczegółowo

Temat: Ułatwienia wynikające z zastosowania Frameworku CakePHP podczas budowania stron internetowych

Temat: Ułatwienia wynikające z zastosowania Frameworku CakePHP podczas budowania stron internetowych PAŃSTWOWA WYŻSZA SZKOŁA ZAWODOWA W ELBLĄGU INSTYTUT INFORMATYKI STOSOWANEJ Sprawozdanie z Seminarium Dyplomowego Temat: Ułatwienia wynikające z zastosowania Frameworku CakePHP podczas budowania stron internetowych

Bardziej szczegółowo

Zadanie polega na stworzeniu bazy danych w pamięci zapewniającej efektywny dostęp do danych baza osób.

Zadanie polega na stworzeniu bazy danych w pamięci zapewniającej efektywny dostęp do danych baza osób. Zadanie: Zadanie polega na stworzeniu bazy danych w pamięci zapewniającej efektywny dostęp do danych baza osób. Na kolejnych zajęciach projekt będzie rozwijana i uzupełniana o kolejne elementy omawiane

Bardziej szczegółowo