Tytuł oryginału: C# 6.0 in a Nutshell, 6th...

78

Transcript of Tytuł oryginału: C# 6.0 in a Nutshell, 6th...

Page 1: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:
Page 2: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition

Tłumaczenie: Łukasz Piwko (wstęp, rozdz. 1 – 11, 20 – 24) Robert Górczyński (12 – 18, 26 – 27) Jakub Hubisz (rozdz. 19, 25)

ISBN: 978-83-283-2423-7

© 2016 Helion SA

Authorized Polish translation of the English edition C# 6.0 in a Nutshell, 6th Edition ISBN 9781491927069 © 2016 Joseph Albahari, Ben Albahari.

This translation is published and sold by permission of O’Reilly Media, Inc., which owns or controls all rights to publish and sell the same.

All rights reserved. No part of this book may be reproduced or transmitted in any form or by any means, electronic or mechanical, including photocopying, recording or by any information storage retrieval system, without permission from the Publisher.

Wszelkie prawa zastrzeżone. Nieautoryzowane rozpowszechnianie całości lub fragmentu niniejszej publikacji w jakiejkolwiek postaci jest zabronione. Wykonywanie kopii metodą kserograficzną, fotograficzną, a także kopiowanie książki na nośniku filmowym, magnetycznym lub innym powoduje naruszenie praw autorskich niniejszej publikacji.

Wszystkie znaki występujące w tekście są zastrzeżonymi znakami firmowymi bądź towarowymi ich właścicieli.

Autor oraz Wydawnictwo HELION dołożyli wszelkich starań, by zawarte w tej książce informacje były kompletne i rzetelne. Nie biorą jednak żadnej odpowiedzialności ani za ich wykorzystanie, ani za związane z tym ewentualne naruszenie praw patentowych lub autorskich. Autor oraz Wydawnictwo HELION nie ponoszą również żadnej odpowiedzialności za ewentualne szkody wynikłez wykorzystania informacji zawartych w książce.

Wydawnictwo HELIONul. Kościuszki 1c, 44-100 GLIWICEtel. 32 231 22 19, 32 230 98 63e-mail: [email protected]: http://helion.pl (księgarnia internetowa, katalog książek)

Drogi Czytelniku!Jeżeli chcesz ocenić tę książkę, zajrzyj pod adres http://helion.pl/user/opinie/c6pig6Możesz tam wpisać swoje uwagi, spostrzeżenia, recenzję.

Pliki z przykładami omawianymi w książce można znaleźć pod adresem: ftp://ftp.helion.pl/przyklady/c6pig6.zip

Printed in Poland.

• Kup książkę• Poleć książkę • Oceń książkę

• Księgarnia internetowa• Lubię to! » Nasza społeczność

Page 3: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

3

Spis treści

Wstęp ............................................................................................................................. 11

1 Wprowadzenie do C# i .NET Framework ............................................................................ 17Obiektowość 17Bezpieczeństwo typów 18Zarządzanie pamięcią 19Platformy 19Powiązania C# z CLR 19CLR i .NET Framework 20C# i środowisko wykonawcze systemu Windows 21Co nowego w C# 6.0 22Co było nowego w C# 5.0 24Co było nowego w C# 4.0 24Co było nowego w C# 3.0 25

2 Podstawy języka C# ......................................................................................................... 27Pierwszy program w języku C# 27Składnia 30Podstawy typów 33Typy liczbowe 42Typ logiczny i operatory 49Łańcuchy znaków i pojedyncze znaki 51Tablice 53Zmienne i parametry 57Wyrażenia i operatory 65Operatory null 70Instrukcje 71Przestrzenie nazw 79

Poleć książkęKup książkę

Page 4: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

4 Spis treści

3 Tworzenie typów w języku C# ...........................................................................................87Klasy 87Dziedziczenie 101Typ object 109Struktury 113Modyfikatory dostępu 114Interfejsy 116Wyliczenia 121Typy zagnieżdżone 124Typy generyczne 125

4 Zaawansowane elementy języka C# ...............................................................................139Delegaty 139Zdarzenia 147Wyrażenia lambda 153Metody anonimowe 157Instrukcje try i wyjątki 158Wyliczanie i iteratory 166Typy wartościowe dopuszczające wartość null 171Przeciążanie operatorów 177Metody rozszerzające 180Typy anonimowe 182Wiązanie dynamiczne 183Atrybuty 191Atrybuty informacji wywołującego 193Niebezpieczny kod i wskaźniki 194Dyrektywy preprocesora 198Dokumentacja XML 200

5 Ogólny zarys platformy ..................................................................................................205CLR i rdzeń platformy 207Technologie praktyczne 212

6 Podstawowe wiadomości o platformie ...........................................................................219Obsługa łańcuchów i tekstu 219Data i godzina 232Daty i strefy czasowe 239Formatowanie i parsowanie 244Standardowe łańcuchy formatu i flagi parsowania 250Inne mechanizmy konwersji 257Globalizacja 261Praca z liczbami 262

Poleć książkęKup książkę

Page 5: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

Spis treści 5

Wyliczenia 266Krotki 269Struktura Guid 271Sprawdzanie równości 271Określanie kolejności 281Klasy pomocnicze 284

7 Kolekcje ........................................................................................................................ 289Przeliczalność 289Interfejsy ICollection i IList 296Klasa Array 300Listy, kolejki, stosy i zbiory 308Słowniki 316Kolekcje i pośredniki z możliwością dostosowywania 322Dołączanie protokołów równości i porządkowania 328

8 Zapytania LINQ .............................................................................................................. 335Podstawy 335Składnia płynna 337Wyrażenia zapytań 343Wykonywanie opóźnione 347Podzapytania 353Tworzenie zapytań złożonych 356Strategie projekcji 360Zapytania interpretowane 362LINQ to SQL i Entity Framework 368Budowanie wyrażeń zapytań 381

9 Operatory LINQ .............................................................................................................. 387Informacje ogólne 388Filtrowanie 391Projekcja 395Łączenie 406Porządkowanie 413Grupowanie 416Operatory zbiorów 419Metody konwersji 420Operatory elementów 423Metody agregacyjne 425Kwantyfikatory 429Metody generujące 430

Poleć książkęKup książkę

Page 6: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

6 Spis treści

10 LINQ to XML ...................................................................................................................433Przegląd architektury 433Informacje ogólne o X-DOM 434Tworzenie drzewa X-DOM 437Nawigowanie i wysyłanie zapytań 440Modyfikowanie drzewa X-DOM 444Praca z wartościami 447Dokumenty i deklaracje 450Nazwy i przestrzenie nazw 453Adnotacje 458Projekcja do X-DOM 459

11 Inne technologie XML ....................................................................................................465Klasa XmlReader 466Klasa XmlWriter 474Typowe zastosowania klas XmlReader i XmlWriter 476XSD i sprawdzanie poprawności schematów 480XSLT 483

12 Zwalnianie zasobów i mechanizm usuwania nieużytków ................................................485IDisposable, Dispose i Close 485Automatyczne usuwanie nieużytków 491Finalizatory 493Jak działa mechanizm usuwania nieużytków? 498Wycieki pamięci zarządzanej 503Słabe odwołania 507

13 Diagnostyka i kontrakty kodu .........................................................................................511Kompilacja warunkowa 511Debugowanie i klasy monitorowania 515Ogólne omówienie kontraktów kodu 518Warunki początkowe 523Warunki końcowe 527Asercje i metody inwariantów obiektu 529Kontrakty w interfejsach i metodach abstrakcyjnych 531Rozwiązywanie problemów z awariami podczas użycia kontraktów 532Selektywne egzekwowanie kontraktów 534Statyczne sprawdzenie kontraktu 536Integracja z debuggerem 538Procesy i wątki procesów 539Klasy StackTrace i StackFrame 540Dziennik zdarzeń Windows 542

Poleć książkęKup książkę

Page 7: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

Spis treści 7

Liczniki wydajności 544Klasa Stopwatch 549

14 Współbieżność i asynchroniczność .................................................................................. 551Wprowadzenie 551Wątkowanie 552Zadania 569Reguły asynchroniczności 577Funkcje asynchroniczne w języku C# 582Wzorce asynchroniczności 598Wzorce uznane za przestarzałe 606

15 Strumienie i wejście-wyjście .......................................................................................... 611Architektura strumienia 611Użycie strumieni 613Adapter strumienia 626Kompresja strumienia 634Praca z plikami w postaci archiwum ZIP 636Operacje na plikach i katalogach 637Plikowe operacje wejścia-wyjścia w środowisku uruchomieniowym Windows 648Mapowanie plików w pamięci 650Odizolowany magazyn danych 653

16 Sieć ............................................................................................................................... 661Architektura sieci 661Adresy i porty 664Adresy URI 665Klasy po stronie klienta 667Praca z HTTP 680Utworzenie serwera HTTP 685Użycie FTP 688Użycie DNS 690Wysyłanie poczty elektronicznej za pomocą SmtpClient 691Użycie TCP 692Otrzymywanie poczty elektronicznej POP3 za pomocą TCP 695TCP w środowisku uruchomieniowym Windows 697

17 Serializacja .................................................................................................................... 699Koncepcje serializacji 699Serializacja kontraktu danych 703Kontrakty danych i kolekcje 713Rozszerzenie kontraktu danych 715

Poleć książkęKup książkę

Page 8: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

8 Spis treści

Serializacja binarna 718Atrybuty serializacji binarnej 720Serializacja binarna za pomocą ISerializable 724Serializacja XML 727

18 Podzespoły ....................................................................................................................737Co znajduje się w podzespole? 737Silne nazwy i podpisywanie podzespołu 742Nazwy podzespołów 745Technologia Authenticode 748Global Assembly Cache 751Zasoby i podzespoły satelickie 754Wyszukiwanie i wczytywanie podzespołów 762Wdrażanie podzespołów poza katalogiem bazowym 768Umieszczenie w pojedynczym pliku wykonywalnym 769Praca z podzespołami, do których nie ma odwołań 771

19 Refleksje i metadane .....................................................................................................773Refleksje i aktywacja typów 774Refleksje i wywoływanie składowych 780Refleksje dla podzespołów 792Praca z atrybutami 793Generowanie dynamicznego kodu 799Emitowanie podzespołów i typów 805Emitowanie składowych typów 809Emitowanie generycznych typów i klas 814Kłopotliwe cele emisji 816Parsowanie IL 819

20 Programowanie dynamiczne ..........................................................................................825Dynamiczny system wykonawczy języka 825Unifikacja typów liczbowych 827Dynamiczne wybieranie przeciążonych składowych 828Implementowanie obiektów dynamicznych 833Współpraca z językami dynamicznymi 836

21 Bezpieczeństwo .............................................................................................................839Uprawnienia 839Zabezpieczenia dostępu kodu 843Dopuszczanie częściowo zaufanych wywołujących 846Model transparentności 848

Poleć książkęKup książkę

Page 9: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

Spis treści 9

Ograniczanie innego zestawu 856Zabezpieczenia systemu operacyjnego 860Tożsamości i role 862Kryptografia 864Windows Data Protection 864Obliczanie skrótów 865Szyfrowanie symetryczne 867Szyfrowanie kluczem publicznym i podpisywanie 871

22 Zaawansowane techniki wielowątkowości ..................................................................... 877Przegląd technik synchronizacji 878Blokowanie wykluczające 878Blokady i bezpieczeństwo ze względu na wątki 886Blokowanie bez wykluczania 892Sygnalizacja przy użyciu uchwytów zdarzeń oczekiwania 897Klasa Barrier 905Leniwa inicjalizacja 906Pamięć lokalna wątku 909Metody Interrupt i Abort 911Metody Suspend i Resume 912Zegary 913

23 Programowanie równoległe .......................................................................................... 917Dlaczego PFX? 917PLINQ 920Klasa Parallel 933Równoległe wykonywanie zadań 939Klasa AggregateException 948Kolekcje współbieżne 951Klasa BlockingCollection<T> 954

24 Domeny aplikacji ........................................................................................................... 959Architektura domeny aplikacji 959Tworzenie i likwidowanie domen aplikacji 961Posługiwanie się wieloma domenami aplikacji 962Metoda DoCallBack 964Monitorowanie domen aplikacji 965Domeny i wątki 965Dzielenie danych między domenami 967

Poleć książkęKup książkę

Page 10: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

10 Spis treści

25 Współpraca ....................................................................................................................973Odwołania do natywnych bibliotek DLL 973Szeregowanie 974Wywołania zwrotne z kodu niezarządzanego 977Symulowanie unii C 977Pamięć współdzielona 978Mapowanie struktury na pamięć niezarządzaną 981Współpraca COM 985Wywołanie komponentu COM z C# 986Osadzanie typów współpracujących 990Główne moduły współpracujące 990Udostępnianie obiektów C# dla COM 991

26 Wyrażenia regularne .....................................................................................................993Podstawy wyrażeń regularnych 994Kwantyfikatory 998Asercje o zerowej wielkości 999Grupy 1002Zastępowanie i dzielenie tekstu 1003Receptury wyrażeń regularnych 1005Leksykon języka wyrażeń regularnych 1008

27 Kompilator Roslyn ....................................................................................................... 1013Architektura Roslyn 1014Drzewa składni 1015Kompilacja i model semantyczny 1030

Skorowidz ................................................................................................................... 1041

Poleć książkęKup książkę

Page 11: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

289

7Kolekcje

Platforma .NET Framework zapewnia standardowy zestaw typów do sortowania i obsługiwaniakolekcji obiektów. Wśród nich można znaleźć listy o zmiennym rozmiarze, listy powiązane, sortowanei niesortowane słowniki oraz tablice. Z tych wszystkich typów jedynie tablice należą do języka C#.Pozostałe kolekcje są tylko klasami, których obiekty można tworzyć tak samo jak obiekty wszystkichinnych klas.

Typy kolekcji platformy można podzielić na następujące kategorie:

interfejsy definiujące standardowe protokoły kolekcji;

gotowe do użycia klasy kolekcji (listy, słowniki itd.);

klasy bazowe do pisania kolekcji specjalnie dostosowanych do potrzeb konkretnych aplikacji.

W tym rozdziale opisujemy wszystkie te kategorie oraz dodatkowo poświęcamy nieco miejsca typomwykorzystywanym do porównywania i porządkowania elementów.

Oto wykaz przestrzeni nazw, w których znajdują się różne kolekcje.

Przestrzeń nazw Zawartość

System.Collections Niegeneryczne klasy i interfejsy kolekcji

System.Collections.Specialized Silnie typizowane niegeneryczne klasy kolekcji

System.Collections.Generic Generyczne klasy i interfejsy kolekcji

System.Collections.ObjectModel Klasy pośrednie i bazowe do tworzenia niestandardowych kolekcji

System.Collections.Concurrent Kolekcje bezpieczne wątkowo (zob. rozdział 23.)

PrzeliczalnośćIstnieje wiele różnych rodzajów kolekcji, od prostych struktur danych, przez tablice i listy powiązanepo złożone struktury, takie jak drzewa czerwono-czarne i tablice skrótów. Choć konstrukcje teznacznie różnią się pod względem budowy zarówno wewnętrznych, jak i zewnętrznych cech, prawiewszystkie z nich można przeglądać. Platforma .NET zapewnia tę możliwość przez dwa interfejsy

Poleć książkęKup książkę

Page 12: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

290 Rozdział 7. Kolekcje

(IEnumerable i IEnumerator oraz ich generyczne odpowiedniki), dzięki którym różne struktury danychudostępniają jednakowy interfejs API do przeglądania ich zawartości. Wymienione interfejsy należądo szerszego zbioru przedstawionego na rysunku 7.1.

Rysunek 7.1. Interfejsy kolekcji

Interfejsy IEnumerable i IEnumeratorInterfejs IEnumerator definiuje podstawowy niskopoziomowy protokół określający sposób przeglą-dania elementów kolekcji do przodu. Jego deklaracja wygląda tak:

public interface IEnumerator{ bool MoveNext(); object Current { get; } void Reset();}

Metoda MoveNext przesuwa bieżący element zwany kursorem o jedną pozycję dalej i zwraca fałsz,jeśli był to ostatni element tej kolekcji. Metoda Current zwraca bieżący element (zazwyczaj rzutowanyz typu object na bardziej konkretny typ). Metoda MoveNext musi zostać wywołana przed pobraniempierwszego elementu — zasadę tę wprowadzono, aby było możliwe tworzenie pustych kolekcji.Metoda Reset, jeśli jest zaimplementowana, przenosi kursor z powrotem na początek, aby możnabyło od nowa przejrzeć kolekcję. Metoda ta znajduje zastosowanie głównie przy współpracy z tech-nologią COM. Raczej nie wywołuje się jej bezpośrednio, ponieważ nie jest wszędzie obsługiwana(ani niezbędna, gdyż w większości przypadków równie dobrze można utworzyć nowy enumerator).

Tylko nieliczne kolekcje implementują enumeratory. Większość udostępnia enumeratory przezinterfejs IEnumerable:

public interface IEnumerable{ IEnumerator GetEnumerator();}

Dzięki definicji tylko jednej metody zwracającej enumerator interfejs IEnumerable zapewnia ela-styczność umożliwiającą dostarczenie logiki iteracji w innej klasie. Ponadto dzięki temu kolekcjęmoże przeglądać kilku konsumentów jednocześnie i w żaden sposób nie będą sobie przeszkadzać.Interfejs IEnumerable można traktować jak „IEnumeratorProvider” i jest to najbardziej podstawowyinterfejs implementowany przez klasy kolekcji.

Poleć książkęKup książkę

Page 13: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

Przeliczalność 291

Poniżej znajduje się przykład niskopoziomowego wykorzystania interfejsów IEnumerable i IEnumerator:string s = "Cze ";

// klasa string implementuje interfejs IEnumerable, wi c mo emy wywo a metod GetEnumerator():IEnumerator rator = s.GetEnumerator();

while (rator.MoveNext()){ char c = (char) rator.Current; Console.Write (c + ".");}

// wynik: C.z.e. . .

Jednak taki bezpośredni sposób wywoływania metod na enumeratorach należy do rzadkości, ponie-waż w języku C# istnieje wygodny skrót składniowy w postaci instrukcji foreach. Oto ten samprzykład napisany z użyciem tej właśnie instrukcji:

string s = "Cze "; // klasa string implementuje interfejs IEnumerable

foreach (char c in s) Console.Write (c + ".");

Interfejsy IEnumerable<T> i IEnumerator<T>Interfejsy IEnumerator i IEnumerable są prawie zawsze implementowane w parze ze swoimi rozszerzo-nymi generycznymi wersjami:

public interface IEnumerator<T> : IEnumerator, IDisposable{ T Current { get; }}

public interface IEnumerable<T> : IEnumerable{ IEnumerator<T> GetEnumerator();}

Dzięki definicjom typizowanych wersji metod Current i GetEnumerator interfejsy te wzmacniająbezpieczeństwo typów, eliminują konieczność pakowania elementów typów wartościowych orazsą wygodniejsze w użyciu. Tablice automatycznie implementują interfejs IEnumerable<T> (gdzie T jesttypem elementów przechowywanych w tablicy).

Dzięki zwiększonemu bezpieczeństwu dla typów wywołanie poniższej metody z tablicą znakówspowoduje błąd kompilacji:

void Test (IEnumerable<int> numbers) { ... }

W klasach kolekcji standardowo udostępnia się publicznie elementy interfejsu IEnumerable<T>,a „ukrywa” elementy niegenerycznego interfejsu IEnumerable przez zastosowanie jawnej implementa-cji tego pierwszego. Dzięki temu, jeśli programista bezpośrednio wywoła metodę GetEnumerator(),to otrzyma bezpieczny pod względem typów IEnumerator<T>. Zdarzają się jednak przypadki złamaniatej zasady ze względu na zgodność ze starym kodem (typy generyczne wprowadzono dopiero w C# 2.0).Dobrym przykładem są tablice, które muszą zwracać niegeneryczny (można ładniej powiedzieć:klasyczny) IEnumerator, aby nie spowodować awarii starych partii kodu. Aby otrzymać generycz-ny IEnumerator<T>, należy dokonać rzutowania, by udostępnić jawny interfejs:

Poleć książkęKup książkę

Page 14: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

292 Rozdział 7. Kolekcje

int[] data = { 1, 2, 3 };var rator = ((IEnumerable <int>)data).GetEnumerator();

Na szczęście dzięki instrukcji foreach rzadko jest to konieczne.

Interfejsy IEnumerable<T> i IDisposable

IEnumerator<T> dziedziczy po IDisposable. Dzięki temu enumeratory mogą przechowywać referencjedo takich zasobów jak połączenia z bazą danych i zwalniać je po zakończeniu lub przerwaniu pracy.Instrukcja foreach „ma świadomość” tego szczegółu i tłumaczy taki kod:

foreach (var element in somethingEnumerable) { ... }

na następujący logiczny ekwiwalent:using (var rator = somethingEnumerable.GetEnumerator()) while (rator.MoveNext()) { var element = rator.Current; ... }

Kiedy używać interfejsów niegenerycznychBiorąc pod uwagę zwiększone bezpieczeństwo typowe generycznych interfejsów kolekcji, takich jakIEnumerable<T>, można zadać pytanie: czy niegeneryczna wersja IEnumerable (lub ICollection alboIList) w ogóle jest do czegoś potrzebna?

Jeśli chodzi o interfejs IEnumerable, to musi być implementowany w połączeniu z IEnumerable<T>,ponieważ ten drugi korzysta z pierwszego. Jednak niezmiernie rzadko pisze się implementacje tychinterfejsów od początku — najczęściej można wykorzystać metody iteracyjne, Collection<T> oraz LINQ.

A co z konsumentem? Prawie zawsze wystarczają interfejsy generyczne. Wprawdzie niegeneryczne wersjeteż są czasami przydatne, choć raczej do zapewnienia spójności typów wszystkich elementów kolekcji.Poniższa metoda np. rekurencyjnie liczy elementy w każdej kolekcji:

public static int Count (IEnumerable e){ int count = 0; foreach (object element in e) { var subCollection = element as IEnumerable; if (subCollection != null) count += Count (subCollection); else count++; } return count;}

Ponieważ w języku C# występuje kowariancja interfejsów generycznych, można się spodziewać, że tametoda powinna przyjmować typ IEnumerable<object>. To jednak nie udałoby się z elementamitypów wartościowych i ze starymi kolekcjami, które nie implementują interfejsu IEnumerable<T> —przykładem jest ControlCollection z Windows Forms.

Tak na marginesie: uważny czytelnik mógł zauważyć w naszym przykładzie potencjalny błąd — cyklicznereferencje spowodują nieskończoną rekurencję i awarię metody. Problem ten można łatwo usunąć,używając kolekcji HashSet (zob. sekcję „Klasy HashSet<T> i SortedSet<T>”).

Poleć książkęKup książkę

Page 15: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

Przeliczalność 293

Blok using zapewnia odpowiednie załatwienie zasobów — szerzej na temat interfejsu IDisposablepiszemy w rozdziale 12.

Implementowanie interfejsów przeliczeniowychInterfejsy IEnumerable i IEnumerable<T> można zaimplementować z następujących powodów:

aby umożliwić korzystanie z instrukcji foreach;

aby zapewnić możliwość współpracy ze wszystkim, co oczekuje standardowej kolekcji;

aby spełnić wymagania bardziej zaawansowanego interfejsu kolekcji;

aby obsługiwać inicjalizatory kolekcji.

Aby zaimplementować interfejs IEnumerable lub IEnumerable<T>, należy dostarczyć enumerator.Można to zrobić na jeden z trzech sposobów:

jeżeli klasa „opakowuje” inną kolekcję, można zwrócić enumerator tej opakowanej kolekcji;

przez iterator za pomocą instrukcji yield return;

tworząc własną implementację interfejsu IEnumerable lub IEnumerable<T>.

Można też utworzyć podklasę istniejącej kolekcji. Klasa Collection<T> służy właśniedo tego celu (zob. podrozdział „Kolekcje i pośredniki z możliwością dostosowywania”).Inną możliwością jest użycie operatorów zapytań LINQ, o których mowa w następnymrozdziale.

Zwrócenie enumeratora innej kolekcji jest zaledwie kwestią wywołania metody GetEnumerator nawewnętrznej kolekcji. Jednak takie rozwiązanie jest możliwe jedynie w najprostszych przypadkach,gdy elementy wewnętrznej kolekcji są dokładnie tym, czym powinny być. Bardziej elastycznerozwiązanie polega na napisaniu iteratora przy użyciu instrukcji yield return. Iterator to elementjęzyka C# pomocny w pisaniu kolekcji na podobnej zasadzie, jak instrukcja foreach jest pomocnaw ich konsumowaniu. Iterator automatycznie rozwiązuje kwestię implementacji interfejsów IEnumerablei IEnumerator lub ich generycznych wersji. Oto prosty przykład:

public class MyCollection : IEnumerable{ int[] data = { 1, 2, 3 };

public IEnumerator GetEnumerator() { foreach (int i in data) yield return i; }}

Zwróć uwagę na zawartą w tym kodzie „czarną magię” — metoda GetEnumerator nie wygląda tak,jakby miała zwracać enumerator! Kompilator, parsując instrukcję yield return, tworzy ukrytą za-gnieżdżoną klasę enumeratora, a następnie refaktoryzuje metodę GetEnumerator w taki sposób,aby tworzyła i zwracała egzemplarz tej klasy. Iteratory są proste i potężne (i często znajdują zastosowa-nie w implementacji standardowych operatorów zapytań LINQ to Object).

Poleć książkęKup książkę

Page 16: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

294 Rozdział 7. Kolekcje

Zgodnie z tą linią możemy też zaimplementować generyczny interfejs IEnumerable<T>:public class MyGenCollection : IEnumerable<int>{ int[] data = { 1, 2, 3 };

public IEnumerator<int> GetEnumerator() { foreach (int i in data) yield return i; }

IEnumerator IEnumerable.GetEnumerator() // jawna implementacja { // ukrywa go return GetEnumerator(); }}

Jako że interfejs IEnumerable<T> dziedziczy po IEnumerable, musimy zaimplementować zarównogeneryczną, jak i niegeneryczną wersję metody GetEnumerator. Dodatkowo zgodnie ze standardowąpraktyką zaimplementowaliśmy też jawnie niegeneryczną wersję. Może ona po prostu wywoływaćgeneryczną metodę GetEnumerator, ponieważ interfejs IEnumerator<T> dziedziczy po IEnumerator.

Napisana przez nas klasa mogłaby zostać wykorzystana jako baza do napisania bardziej zaawanso-wanej kolekcji. Jeśli jednak potrzebna jest tylko prosta implementacja interfejsu IEnumerable<T>,instrukcja yield return umożliwia skorzystanie z prostszego rozwiązania. Zamiast pisać klasę, logikęiteracji można umieścić w metodzie zwracającej generyczną kolekcję typu IEnumerable<T> i resztęzostawić kompilatorowi. Oto przykład:

public class Test{ public static IEnumerable <int> GetSomeIntegers() { yield return 1; yield return 2; yield return 3; }}

A oto przykład użycia naszej metody:foreach (int i in Test.GetSomeIntegers()) Console.WriteLine (i);

// wynik123

Ostatnim sposobem napisania metody GetEnumerator jest napisanie klasy bezpośrednio implementu-jącej interfejs IEnumerator. Dokładnie to robi kompilator niejawnie, przy rozpoznawaniu iteratorów.(Na szczęście nieczęsto trzeba posuwać się tak daleko we własnym kodzie). Poniżej znajduje sięprzykład kolekcji z wpisanymi na stałe wartościami 1, 2 i 3:

public class MyIntList : IEnumerable{ int[] data = { 1, 2, 3 };

Poleć książkęKup książkę

Page 17: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

Przeliczalność 295

public IEnumerator GetEnumerator() { return new Enumerator (this); }

class Enumerator : IEnumerator // definicja wewn trznej klasy { // dla enumeratora MyIntList collection; int currentIndex = -1;

public Enumerator (MyIntList collection) { this.collection = collection; }

public object Current { get { if (currentIndex == -1) throw new InvalidOperationException ("Enumeracja nie zosta a rozpocz ta!"); if (currentIndex == collection.data.Length) throw new InvalidOperationException ("Za ko cem listy!"); return collection.data [currentIndex]; } }

public bool MoveNext() { if (currentIndex >= collection.data.Length - 1) return false; return ++currentIndex < collection.data.Length; }

public void Reset() { currentIndex = -1; } }}

Implementacja metody Reset jest nieobowiązkowa — ewentualnie można zgłaszaćwyjątek NotSupportedException.

Podkreślmy, że pierwsze wywołanie metody MoveNext powinno powodować przejście do pierwszego(a nie drugiego) elementu listy.

Aby uzyskać funkcjonalność zbliżoną do iteratora, musimy jeszcze dodatkowo zaimplementować in-terfejs IEnumerator<T>. Poniżej przedstawiamy przykład z pominięciem testów granic dla uproszczenia:

class MyIntList : IEnumerable<int>{ int[] data = { 1, 2, 3 };

// Generyczny enumerator jest zgodny zarówno z IEnumerable, jak i IEnumerable<T>. // Implementujemy niegeneryczn metod GetEnumerator jawnie, aby unikn konfliktów nazw.

public IEnumerator<int> GetEnumerator() { return new Enumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return new Enumerator(this); }

Poleć książkęKup książkę

Page 18: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

296 Rozdział 7. Kolekcje

class Enumerator : IEnumerator<int> { int currentIndex = -1; MyIntList collection;

public Enumerator (MyIntList collection) { this.collection = collection; }

public int Current => collection.data [currentIndex];

object IEnumerator.Current => Current;

public bool MoveNext() => ++currentIndex < collection.data.Length;

public void Reset() => currentIndex = -1; // Je li nie jest potrzebna metoda Dispose, to dobrym zwyczajem jest jej // jawne zaimplementowanie tak, aby by a niedost pna w interfejsie publicznym. void IDisposable.Dispose() {} }}

Przykład z użyciem typów generycznych jest szybszy, ponieważ metoda IEnumerator<int>.Currentnie wymaga rzutowania z int na object, a więc eliminuje pakowanie.

Interfejsy ICollection i IListChoć interfejsy enumeracyjne stanowią protokół iteracji kolekcji tylko do przodu, nie zapewniająmożliwości sprawdzania rozmiaru kolekcji, dostępu do składowych za pomocą indeksów, przeszu-kiwania struktur danych ani ich modyfikowania. Wszystkie te funkcje zapewniają interfejsy .NETFramework ICollection, IList oraz IDictionary. Każdy z nich występuje w wersji generycznej i nie-generycznej, choć te drugie istnieją głównie ze względu na zgodność ze starym kodem.

Hierarchia dziedziczenia tych interfejsów jest pokazana na rysunku 7.1. Najprościej można je podsu-mować w następujący sposób:

IEnumerable<T> (i IEnumerable)Zapewnia minimalną funkcjonalność (tylko przeglądanie).

ICollection<T> (i ICollection)Zapewnia średni poziom funkcjonalności (np. własność Count).

IList <T>/IDictionary <K,V> i ich niegeneryczne wersjeZapewnia najwyższy poziom funkcjonalności (wliczając dostęp „swobodny” przy użyciu indek-sów i kluczy).

Konieczność implementowania któregokolwiek z tych interfejsów jest rzadkością.Gdy trzeba napisać klasę kolekcji, to prawie zawsze można wykorzystać do tego klasę ba-zową Collection<T> (zob. podrozdział „Kolekcje i pośredniki z możliwością dostosowy-wania”). W niektórych przypadkach inną możliwość zapewnia też technologia LINQ.

Poleć książkęKup książkę

Page 19: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

Interfejsy ICollection i IList 297

Różnice między wersjami generycznymi i niegenerycznymi są większe niż można się spodziewać,zwłaszcza w przypadku interfejsu ICollection. Przyczyny tego są w głównej mierze historyczne — typygeneryczne powstały później, więc interfejsy generyczne tworzono z pewnym bagażem doświadczenia,dzięki czemu udało się dobrać inne (i lepsze) składowe. Dlatego właśnie interfejs ICollection<T> nierozszerza interfejsu ICollection, IList<T> nie rozszerza interfejsu IList, a IDictionary<TKey,TValue> nie rozszerza interfejsu IDictionary. Oczywiście klasa kolekcji może implementować obiewersje interfejsu, jeśli jest to korzystne (a często jest).

Innym, mniej oczywistym powodem, dla którego IList<T> nie rozszerza interfejsuIList, jest to, że rzutowanie na IList<T> zwracałoby interfejs ze składowymi Add(T)i Add(object). To z kolei oznaczałoby zniweczenie bezpieczeństwa typowego, po-nieważ można byłoby wywołać metodę Add z obiektem dowolnego typu.

W tym podrozdziale są opisane interfejsy ICollection<T>, IList<T> i ich niegeneryczne wersje.Opis interfejsów słownikowych znajduje się w podrozdziale „Słowniki”.

W obrębie platformy .NET Framework słowa kolekcja i lista są używane bez dającejsię uchwycić logiki. Na przykład interfejs IList<T> jest bardziej funkcjonalną wersjąinterfejsu ICollection<T>, więc można oczekiwać, że klasa List<T> będzie tak samobardziej funkcjonalna niż klasa Collection<T>. Jednak tak nie jest. Dlatego terminykolekcja i lista najlepiej traktować jako synonimy, chyba że chodzi o konkretny typ.

Interfejsy ICollection<T> i ICollectionICollection<T> to standardowy interfejs dla policzalnych kolekcji obiektów. Zapewnia możliwośćsprawdzenia rozmiaru kolekcji (Count), sprawdzenia, czy dany element znajduje się w kolekcji(Contains), skopiowania kolekcji do tablicy (ToArray) oraz stwierdzenia, czy strukturę można modyfi-kować (IsReadOnly). W przypadku kolekcji z możliwością zapisu dostępne są także operacje Add,Remove i Clear. A ponieważ interfejs ten rozszerza IEnumerable<T>, kolekcje można przeglądać zapomocą instrukcji foreach:

public interface ICollection<T> : IEnumerable<T>, IEnumerable{ int Count { get; }

bool Contains (T item); void CopyTo (T[] array, int arrayIndex); bool IsReadOnly { get; }

void Add(T item); bool Remove (T item); void Clear();}

Niegeneryczny interfejs ICollection także opisuje policzalną kolekcję, ale nie zapewnia funkcjido modyfikowania listy ani sprawdzania, czy zawiera określony element:

public interface ICollection : IEnumerable{ int Count { get; } bool IsSynchronized { get; }

Poleć książkęKup książkę

Page 20: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

298 Rozdział 7. Kolekcje

object SyncRoot { get; } void CopyTo (Array array, int index);}

Niegeneryczny interfejs dodatkowo definiuje własności przydatne w synchronizacji (rozdział 14.)— wstawiono je do wersji generycznej, ponieważ bezpieczeństwo wątków nie jest już uważane zacechę wewnętrzną kolekcji.

Implementacja obu interfejsów jest łatwa. W przypadku implementacji interfejsu tylko do odczytuICollection<T> metody Add, Remove i Clear powinny zgłaszać wyjątek NotSupportedException.

Z reguły interfejsy te implementuje się łącznie z IList lub IDictionary.

Interfejsy IList<T> i IListIList<T> to standardowy interfejs kolekcji indeksowanych pozycyjnie. Oprócz składników odziedzi-czonych z interfejsów ICollection<T> i IEnumerable<T> zawiera funkcje pozwalające odczytywać,zapisywać (za pomocą indeksatora), wstawiać oraz usuwać elementy wg pozycji:

public interface IList<T> : ICollection<T>, IEnumerable<T>, IEnumerable{ T this [int index] { get; set; } int IndexOf (T item); void Insert (int index, T item); void RemoveAt (int index);}

Metody IndexOf wykonują przeszukiwanie liniowe listy i zwracają wartość -1, jeśli nie znajdąszukanego elementu.

Niegeneryczna wersja interfejsu IList ma więcej składowych, ponieważ mniej dziedziczy poICollection:

public interface IList : ICollection, IEnumerable{ object this [int index] { get; set } bool IsFixedSize { get; } bool IsReadOnly { get; } int Add (object value); void Clear(); bool Contains (object value); int IndexOf (object value); void Insert (int index, object value); void Remove (object value); void RemoveAt (int index);}

Metoda Add niegenerycznego interfejsu IList zwraca liczbę całkowitą będącą indeksem nowo do-danego elementu. Dla porównania metoda Add interfejsu ICollection<T> ma typ zwrotny void.

Ogólna klasa List<T> jest typową implementacją interfejsów IList<T> i IList. W języku C# takżetablice implementują zarówno generyczną, jak i niegeneryczną wersję (choć metody dodające i usu-wające elementy są ukryte przez jawną implementację interfejsu i w razie wywołania zgłaszająwyjątek NotSupportedException).

Poleć książkęKup książkę

Page 21: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

Interfejsy ICollection i IList 299

Przy próbie uzyskania dostępu do wielowymiarowej tablicy za pomocą indeksatorainterfejsu IList zgłaszany jest wyjątek ArgumentException. Jest to pułapka dla progra-mistów piszących takie metody jak poniższa:

public object FirstOrNull (IList list){ if (list == null || list.Count == 0) return null; return list[0];}

Na pierwszy rzut oka może się wydawać, że to bardzo solidna funkcja, ale zgłosiwyjątek, jeśli ktoś wywoła ją na tablicy wielowymiarowej. W razie potrzeby w czasiedziałania programu można testować, czy argument nie jest tablicą wielowymiarową,za pomocą poniższego wyrażenia (szerzej na ten temat piszemy w rozdziale 19.):

list.GetType().IsArray && list.GetType().GetArrayRank()>1

Interfejs IReadOnlyList<T>W celu zapewniania możliwości współpracy z kolekcjami tylko do odczytu Windows Runtimew .NET Framework 4.5 wprowadzono nowy interfejs kolekcji o nazwie IReadOnlyList<T>. Jest onjednak przydatny sam w sobie i można go traktować jak okrojoną wersję interfejsu IList<T> udostęp-niającego tylko składowe potrzebne do wykonywania operacji odczytu na listach:

public interface IReadOnlyList<out T> : IEnumerable<T>, IEnumerable{ int Count { get; } T this[int index] { get; }}

Ponieważ parametr typu jest wykorzystywany wyłącznie na pozycjach wyjściowych, oznaczonogo jako kowariantny. Dzięki temu np. listę kotów można traktować jako listę zwierząt tylko do odczy-tu. Natomiast w interfejsie IList<T> parametr T nie jest oznaczony jako kowariantny, ponieważznajduje zastosowanie zarówno na pozycjach wejściowych, jak i wyjściowych.

Interfejs IReadOnlyList<T> reprezentuje widok listy tylko do odczytu. Nie oznaczato jednak, że podstawowa implementacja także musi być tylko do odczytu.

Zgodnie z logiką interfejs IList<T> powinien dziedziczyć po IReadOnlyList<T>. Jednak firmaMicrosoft nie mogła wprowadzić takiej zmiany, ponieważ wymagałaby ona przeniesienia składowychz IList<T> do IReadOnlyList<T>, co spowodowałoby problemy z programami działającymi podkontrolą CLR 4.5 (konsumenci musieliby ponownie skompilować swoje programy, aby uniknąćbłędów wykonawczych). Dlatego implementatorzy interfejsu IList<T> muszą ręcznie dodawać doswoich kolekcji implementację interfejsu IReadOnlyList<T>.

Interfejs IReadOnlyList<T> odpowiada typowi Windows Runtime IVectorView<T>.

Poleć książkęKup książkę

Page 22: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

300 Rozdział 7. Kolekcje

Klasa ArrayKlasa Array to podstawa wszystkich jedno- i wielowymiarowych tablic oraz jeden z podstawowychtypów implementujących standardowe interfejsy kolekcji. Ponieważ zapewnia unifikację typów,wszystkie tablice dysponują takim samym zestawem metod, niezależnie od ich deklaracji i typuelementów.

Ze względu na wielkie znaczenie tablic w języku C# utworzono specjalną składnię do ich deklaro-wania i inicjalizowania, której opis znajduje się w rozdziałach 2. i 3. Gdy programista deklarujetablicę za pomocą składni C#, system CLR niejawnie generuje podtyp klasy Array, tworząc pseudotypo odpowiednich wymiarach i typie elementów. Ten typ implementuje typizowane generyczne inter-fejsy kolekcji, np. IList<string>.

Ponadto system CLR traktuje typy tablicowe w specjalny sposób, przypisując tworzonym obiektomciągły obszar pamięci. Dzięki temu indeksowanie jest bardzo szybkie, ale za cenę braku możliwościzwiększenia rozmiaru struktury w późniejszym czasie.

Klasa Array implementuje interfejsy kolekcji do IList<T> w wersjach generycznych i niegenerycz-nych. Natomiast interfejs IList<T> jest zaimplementowany jawnie w celu utrzymania porządkuw interfejsie publicznym tablicy, który nie może udostępniać takich metod jak Add czy Remove,ponieważ zgłaszają one wyjątki, jeśli wywoła się je na kolekcji o niezmiennym rozmiarze. Wprawdzieklasa Array udostępnia statyczną metodę o nazwie Resize do zmieniania rozmiaru tablicy, ale jejdziałanie polega na utworzeniu nowej tablicy i skopiowaniu do niej wszystkich elementów. Niedość, że ta operacja jest bardziej nieefektywna, to na dodatek wszystkie znajdujące się w różnychmiejscach programu referencje nadal będą wskazywać starą strukturę. Jeśli potrzebny jestobiekt o zmiennym rozmiarze, to lepiej użyć klasy List<T> (opisanej w następnym podrozdziale).

W tablicy można przechowywać elementy typów zarówno wartościowych, jak i referencyjnych.Elementy wartościowe są przechowywane bezpośrednio w tablicy, więc struktura zawierająca trzyliczby całkowite (każda po 8 bajtów) zajmuje ciągły obszar pamięci o rozmiarze 24 bajtów. Natomiastelementy typów referencyjnych zajmują w tablicy tylko tyle miejsca, ile potrzeba do przechowywaniareferencji (4 bajty w środowisku 32-bitowym i 8 bajtów w środowisku 64-bitowym). Na rysunku 7.2pokazano, co dzieje się w pamięci po wykonaniu poniższego programu:

StringBuilder[] builders = new StringBuilder [5];builders [0] = new StringBuilder ("builder1");builders [1] = new StringBuilder ("builder2");builders [2] = new StringBuilder ("builder3");

long[] numbers = new long [3];numbers [0] = 12345;numbers [1] = 54321;

Jako że Array to klasa, same tablice są typami referencyjnymi, niezależnie od rodzaju przechowywa-nych w nich elementów. Oznacza to, że wynikiem wykonania instrukcji tablicaB = tablicaA będziepowstanie dwóch zmiennych odnoszących się do tej samej tablicy. Jednocześnie test równościdwóch różnych tablic zawsze będzie miał wynik negatywny, chyba że programista użyje własnego

Poleć książkęKup książkę

Page 23: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

Klasa Array 301

Rysunek 7.2. Tablice w pamięci

komparatora. Jeden taki komparator wprowadzono w .NET Framework 4.0, aby umożliwić porów-nywanie elementów w tablicach lub krotkach. Dostęp do niego można uzyskać przez typ StructuralComparisons:object[] a1 = { "string", 123, true };object[] a2 = { "string", 123, true };

Console.WriteLine (a1 == a2); // fa szConsole.WriteLine (a1.Equals (a2)); // fa sz

IStructuralEquatable se1 = a1;Console.WriteLine (se1.Equals (a2, StructuralComparisons.StructuralEqualityComparer)); // prawda

Tablice można kopiować za pomocą metody Clone: tablicaB = tablicaA.Clone(). Jednak w tensposób można wykonać kopię płytką, czyli obejmującą tylko reprezentowany przez tablicę obszarpamięci. Jeżeli struktura zawiera elementy typów wartościowych, to zostaną one skopiowane. Alejeżeli tablica zawiera obiekty typów referencyjnych, to skopiowane zostaną tylko referencje (w efekciepowstaną dwie tablice, których składowe odnoszą się do tych samych obiektów). Na rysunku 7.3przedstawiono skutek dodania do naszego przykładu poniższego kodu:

StringBuilder[] builders2 = builders;StringBuilder[] shallowClone = (StringBuilder[]) builders.Clone();

Jeśli potrzebna jest kopia głęboka — z duplikatami wszystkich obiektów typu referencyjnego —należy przejrzeć tablicę za pomocą pętli i każdy element sklonować ręcznie. Te same zasady dotyczątakże innych typów kolekcji .NET.

Choć klasa Array jest głównie przeznaczona do pracy z indeksatorami 32-bitowymi, to dzięki kilkumetodom przyjmującym parametry Int32 i Int64 do pewnego stopnia obsługuje także indeksatory64-bitowe (co teoretycznie zwiększa jej przestrzeń adresową do 264 elementów). W praktyce te przecią-żone wersje metod są jednak bezużyteczne, ponieważ maksymalny rozmiar obiektu w systemie CLR— w tym także tablic — wynosi 2 GB (zarówno w środowisku 32-bitowym, jak i 64-bitowym).

Poleć książkęKup książkę

Page 24: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

302 Rozdział 7. Kolekcje

Rysunek 7.3. Płytkie kopiowanie tablicy

Wiele z metod klasy Array, które mogą się wydawać metodami egzemplarzowymi,w istocie jest metodami statycznymi. Projektanci tej klasy podjęli dziwną decyzję podtym względem i przez to programista szukający odpowiedniej metody musi sprawdzaćzarówno wśród metod statycznych, jak i egzemplarzowych.

Tworzenie i indeksowanie tablicNajprostszym sposobem na utworzenie i zindeksowanie tablicy jest użycie konstrukcji języka C#:

int[] myArray = { 1, 2, 3 };int first = myArray [0];int last = myArray [myArray.Length - 1];

Ewentualnie tablicę można utworzyć dynamicznie za pomocą metody Array.CreateInstance,która pozwala na określenie typu elementów i liczby wymiarów oraz tworzenie tablic indeksowanychod innego numeru niż zero (przez określenie dolnej granicy). Tablice indeksowane w ten sposóbsą jednak niezgodne z CLS (ang. Common Language Specification).

Dostęp do elementów dynamicznie utworzonej tablicy zapewniają metody GetValue i SetValue(działają też na zwykłych tablicach):

// utworzenie tablicy a cuchów o d ugo ci 2Array a = Array.CreateInstance (typeof(string), 2);a.SetValue ("Witaj,", 0); // a[0] = "Witaj,";a.SetValue (" wiecie", 1); // a[1] = " wiecie";string s = (string) a.GetValue (0); // s = a[0];// istnieje te mo liwo rzutowania na tablice C#string[] cSharpArray = (string[]) a;string s2 = cSharpArray [0];

Tworzone dynamicznie tablice indeksowane od zera można rzutować na tablice C# takiego samegolub zgodnego typu (zgodnego wg zasad wariancji tablic). Jeśli np. klasa Apple jest pochodną klasyFruit, to tablicę typu Apple[] można rzutować na typ Fruit[]. W tym momencie niektórzy mogą

Poleć książkęKup książkę

Page 25: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

Klasa Array 303

się zastanawiać, dlaczego do unifikacji tablicy nie użyto typu object[], tylko klasy Array. Przyczynąjest to, że typ object[] jest niezgodny z wielowymiarowymi tablicami typów wartościowych (a takżeindeksowanych nie od zera). Tablicy typu int[] nie można rzutować na object[]. Dlatego potrzebu-jemy klasy Array w celu zapewnienia kompletnej unifikacji.

Metody GetValue i SetValue działają też na tablicach stworzonych przez kompilator oraz są przy-datne przy pisaniu metod działających na tablicach dowolnego typu i rzędu. Dla tablic wielowymia-rowych przyjmują tablicę indeksatorów:

public object GetValue (params int[] indices)public void SetValue (object value, params int[] indices)

Poniższa metoda drukuje pierwszy element tablicy, niezależnie od tego, ile ma ona wymiarów:void WriteFirstValue (Array a){ Console.Write (a.Rank + "-dimensional; ");

// Tablica indeksatorów automatycznie zainicjalizuje wszystkie warto ci zerami, wi c przekazanie // jej do metody GetValue lub SetValue spowoduje pobranie lub ustawienie pierwszego elementu tablicy.

int[] indexers = new int[a.Rank]; Console.WriteLine ("Pierwsza warto to " + a.GetValue (indexers));}

void Demo(){ int[] oneD = { 1, 2, 3 }; int[,] twoD = { {5,6}, {8,9} };

WriteFirstValue (oneD); // jednowymiarowa; pierwsza warto to 1 WriteFirstValue (twoD); // dwuwymiarowa; pierwsza warto to 5}

Do pracy z tablicami nieznanego typu, ale znanego rzędu można zastosować prostszei efektywniejsze rozwiązanie z wykorzystaniem typów generycznych:void WriteFirstValue<T> (T[] array){ Console.WriteLine (array[0]);}

Metoda SetValue zgłasza wyjątek, jeżeli element jest nieodpowiedniego dla danej tablicy typu.

Gdy tworzona jest tablica, zarówno za pomocą składni języka, jak i metody Array.CreateInstance,jej elementy zostają automatycznie zainicjalizowane. Jeżeli elementy są typu referencyjnego, począt-kowo przypisywana jest im wartość null. Natomiast w przypadku elementów typów wartościowychzostaje wywołany konstruktor domyślny odpowiedniego typu (co w istocie oznacza wyzerowanieskładowych). Ponadto klasa Array zawiera metodę Clear, za pomocą której w dowolnym mo-mencie można wyzerować tablicę:

public static void Clear (Array array, int index, int length);

Metoda ta nie zmienia rozmiaru tablicy, co kłóci się z jej typowym zastosowaniem (np. w ICollection<T>.Clear), polegającym na redukcji struktury do zera elementów.

Poleć książkęKup książkę

Page 26: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

304 Rozdział 7. Kolekcje

Przeglądanie zawartości tablicyZawartość tablicy można łatwo przejrzeć za pomocą instrukcji foreach:

int[] myArray = { 1, 2, 3};foreach (int val in myArray)Console.WriteLine (val);

Ewentualnie można też użyć statycznej metody Array.ForEach o następującej definicji:public static void ForEach<T> (T[] array, Action<T> action);

Wykorzystuje ona delegat Action o następującej sygnaturze:public delegate void Action<T> (T obj);

Tak wygląda pierwszy przykład napisany z użyciem metody Array.ForEach:Array.ForEach (new[] { 1, 2, 3 }, Console.WriteLine);

Długość i liczba wymiarów tablicyW klasie Array dostępne są następujące metody i własności do sprawdzania długości i liczby wymia-rów tablicy:

public int GetLength (int dimension);public long GetLongLength (int dimension);

public int Length { get; }public long LongLength { get; }

public int GetLowerBound (int dimension);public int GetUpperBound (int dimension);

public int Rank { get; } // zwraca liczb wymiarów tablicy

Metody GetLength i GetLongLength zwracają długość wybranego wymiaru (0, jeśli tablica jest jedno-wymiarowa), natomiast metody Length i LongLength zwracają liczbę wszystkich elementów tablicyz wszystkich wymiarów łącznie.

Metody GetLowerBound i GetUpperBound służą do pracy z tablicami indeksowanymi od innego numeruniż zero. Metoda GetUpperBound zwraca wynik równy sumie wartości GetLowerBound i GetLengthdla wybranego wymiaru.

Przeszukiwanie tablicKlasa Array udostępnia bogaty wybór metod do znajdowania elementów w tablicach jednowymia-rowych:

Metody BinarySearchDo szybkiego szukania elementu w posortowanej tablicy.

Metody IndexOf/LastIndexDo szukania elementu w nieposortowanej tablicy.

Find, FindLast, FindIndex, FindLastIndex, FindAll, Exists, TrueForAllDo szukania w nieposortowanych tablicach elementów spełniających warunek Predicate<T>.

Poleć książkęKup książkę

Page 27: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

Klasa Array 305

Żadna z metod przeszukujących nie zgłasza wyjątku, jeśli nie znajdzie szukanej wartości. Zamiasttego metody zwracające liczbę całkowitą zwracają -1 (dla tablic indeksowanych od zera), a metodyzwracające typ generyczny zwracają domyślną wartość tego typu (np. 0 w przypadku int i nullw przypadku string).

Metody przeszukiwania binarnego są szybkie, ale działają tylko na posortowanych tablicach i wyma-gają porównywania elementów pod względem kolejności, a nie równości. W efekcie metody te przyj-mują obiekty typu IComparer i IComparer<T> określające definicję porządku w danym przypadku(zob. sekcję „Dołączanie protokołów równości i porządkowania”). Definicja ta musi być zgodnaz komparatorem użytym pierwotnie do posortowania tablicy. Jeżeli nie zostanie przekazany żadenkomparator, zostanie zastosowany domyślny algorytm porządkujący dla danego typu oparty na jegoimplementacji interfejsu IComparable/IComparable<T>.

Metody IndexOf i LastIndexOf służą do prostego przeglądania elementów tablicy i zwracają numerpierwszej (lub ostatniej) pozycji podanej wartości.

Metody działające na bazie predykatów przyjmują delegaty i wyrażenia lambda pozwalającestwierdzić, czy dana wartość „pasuje” do szukanej. Predykat to po prostu delegat przyjmującyobiekt i zwracający prawdę lub fałsz:

public delegate bool Predicate<T> (T object);

W poniższym przykładzie szukamy w tablicy łańcuchów imienia zawierającego literę a:static void Main(){ string[] names = { "Robert", "Jacek", "Juliusz" }; string match = Array.Find (names, ContainsA); Console.WriteLine (match); // Jacek}static bool ContainsA (string name) { return name.Contains ("a"); }

To jest ten sam kod, tylko skrócony dzięki użyciu metody anonimowej:string[] names = { "Robert", "Jacek", "Juliusz" };string match = Array.Find (names, delegate (string name) { return name.Contains ("a"); } );

Wyrażenie lambda pozwala jeszcze bardziej skrócić kod:string[] names = { "Robert", "Jacek", "Juliusz" };string match = Array.Find (names, n => n.Contains ("a")); // Jacek

Metoda FindAll zwraca tablicę wszystkich elementów spełniających warunek predykatu. Metodata, równoznaczna z Enumerable.Where z przestrzeni nazw System.Linq, zwraca tylko tablicę pasującychelementów, a nie obiekt typu IEnumerable<T>.

Metoda Exists zwraca prawdę, jeżeli którykolwiek element tablicy spełnia warunki danego predykatu,i jest równoważna metodzie Any z System.Linq.Enumerable.

Metoda TrueForAll zwraca prawdę, jeżeli wszystkie elementy spełniają warunek predykatu, i jestrównoważna z All z System.Linq.Enumerable.

Poleć książkęKup książkę

Page 28: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

306 Rozdział 7. Kolekcje

SortowanieKlasa Array ma następujące wbudowane metody sortujące:

// do sortowania pojedynczej tablicy

public static void Sort<T> (T[] array);public static void Sort (Array array);

// do sortowania pary tablic

public static void Sort<TKey,TValue> (TKey[] keys, TValue[] items);public static void Sort (Array keys, Array items);

Każda z tych metod jest dodatkowo przeciążona i przyjmuje:int index // indeks, od którego ma by rozpocz te sortowanieint length // liczba elementów do posortowaniaIComparer<T> comparer // obiekt definiuj cy sposób porównywaniaComparison<T> comparison // delegat definiuj cy sposób porównywania

Poniżej znajduje się najprostszy przykład użycia metody Sort:int[] numbers = { 3, 2, 1 };Array.Sort (numbers); // teraz tablica ma warto ci { 1, 2, 3 }

Metody przyjmujące pary tablic przekładają elementy w każdej z tablic łącznie i opierają decyzjeporządkowe na pierwszej tablicy. W następnym przykładzie zarówno liczby, jak i odpowiadające imsłowa są sortowane w porządku numerycznym:

int[] numbers = { 3, 2, 1 };string[] words = { "trzy", "dwa", "jeden" };Array.Sort (numbers, words);

// teraz kolejno elementów w tablicy numbers to { 1, 2, 3 }// teraz kolejno elementów w tablicy words to { "jeden", "dwa", "trzy" }

Metoda Array.Sort wymaga, aby znajdujące się w tablicy elementy implementowały interfejsIComparable (zob. podrozdział „Określanie kolejności” w rozdziale 6.). Oznacza to, że większośćwbudowanych typów języka C# (takich jak użyte w poprzednim przykładzie liczby całkowite) możnasortować. Jeżeli elementy nie mają określonego wewnętrznego porządku albo programista chcezmienić domyślną kolejność, konieczne jest przekazanie metodzie Sort własnego dostawcy comparisonokreślającego względne ustawienie dwóch elementów. Można to zrobić na dwa sposoby:

przy użyciu pomocniczego obiektu implementującego interfejs IComparer/Icomparer<T> (zob.podrozdział „Dołączanie protokołów równości i porządkowania”);

przy użyciu delegatu Comparison:public delegate int Comparison<T> (T x, T y);

Delegat Comparison posługuje się taką samą semantyką jak metoda IComparer<T>.CompareTo: jeślix jest przed y, zostaje zwrócona ujemna liczba całkowita; jeśli x jest za y, zostaje zwrócona dodatnialiczba całkowita; jeśli x i y zajmują to samo miejsce, zostaje zwrócone 0.

W poniższym przykładzie sortujemy tablicę liczb całkowitych w taki sposób, że najpierw ustawianesą liczby nieparzyste:

Poleć książkęKup książkę

Page 29: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

Klasa Array 307

int[] numbers = { 1, 2, 3, 4, 5 };Array.Sort (numbers, (x, y) => x % 2 == y % 2 ? 0 : x % 2 == 1 ? -1 : 1);// zawarto tablicy numbers to { 1, 3, 5, 2, 4 }

Zamiast metody Sort można też użyć operatorów LINQ OrderBy i ThenBy. W odróż-nieniu od metody Array.Sort operatory LINQ nie zmieniają pierwotnej tablicy, tylkowysyłają posortowane wyniki do nowej sekwencji IEnumerable<T>.

Odwracanie kolejności elementówPoniższe metody klasy Array odwracają kolejność wszystkich lub niektórych elementów tablicy:

public static void Reverse (Array array);public static void Reverse (Array array, int index, int length);

KopiowanieKlasa Array zawiera cztery metody do kopiowania płytkiego: Clone, CopyTo, Copy oraz ConstrainedCopy.Dwie pierwsze są metodami egzemplarzowymi, a pozostałe — statycznymi.

Metoda Clone zwraca nową tablicę (stanowiącą płytką kopię oryginału). Metody CopyTo i Copykopiują ciągły podzbiór elementów tablicy. Kopiowanie wielowymiarowej prostokątnej tablicywymaga przeprowadzenia mapowania wielowymiarowych indeksów na liniowe. Na przykład środko-wy element (position[1,1]) w tablicy o wymiarach 3×3 ma indeks 4, który wynika z obliczeń 1*3+1.Zakresy źródłowy i docelowy mogą się bez problemu nakładać.

Metoda ConstrainedCopy wykonuje operację atomową, tzn. jeśli nie można skopiować wszystkichpotrzebnych elementów (np. z powodu błędnego typu), to cała operacja jest wycofywana.

Ponadto klasa Array zawiera metodę AsReadOnly, która zwraca opakowanie uniemożliwiające ponowneprzypisywanie wartości elementom.

Konwertowanie i zmienianie rozmiarów tablicMetoda Array.ConvertAll tworzy i zwraca nową tablicę typu TOutput. Wywołuje w tym celu przeka-zany jej delegat Converter. Jej definicja wygląda następująco:

public delegate TOutput Converter<TInput,TOutput> (TInput input)

Poniżej znajduje się przykład konwersji tablicy liczb zmiennoprzecinkowych na tablicę liczb całko-witych:

float[] reals = { 1.3f, 1.5f, 1.8f };int[] wholes = Array.ConvertAll (reals, r => Convert.ToInt32 (r));

// zawarto tablicy wholes to { 1, 2, 2 }

Metoda Resize tworzy nową tablicę i kopiuje do niej wszystkie elementy, a następnie zwraca tę nowąstrukturę przez parametr referencyjny. Mimo to referencje do pierwotnej tablicy przechowywanew innych obiektach pozostają niezmienione.

Poleć książkęKup książkę

Page 30: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

308 Rozdział 7. Kolekcje

Przestrzeń System.Linq zawiera dodatkowy asortyment metod do konwersji tablic.Wszystkie one zwracają obiekty typu IEnumerable<T>, który można przekonwertowaćna tablicę za pomocą metody ToArray z klasy Enumerable.

Listy, kolejki, stosy i zbioryPlatforma zapewnia podstawowy zestaw konkretnych klas kolekcji implementujących opisanewcześniej interfejsy. W tym podrozdziale skupiamy się na kolekcjach listowych (których nie należymylić ze strukturami słownikowymi opisanymi w podrozdziale „Słowniki”). Tak jak w przypadkuopisanych wcześniej interfejsów, często mamy do wyboru zarówno generyczne, jak i niegenerycznewersje każdego typu. Pod względem elastyczności i wydajności lepsze są klasy generyczne, przezco ich niegeneryczne odpowiedniki są w zasadzie niepotrzebne z wyjątkiem sytuacji, kiedy trzebazapewnić zgodność ze starym kodem. Jest więc inaczej niż w przypadku interfejsów kolekcji, którebywają przydatne także w wersjach niegenerycznych.

Z opisanych w tym podrozdziale klas najczęściej używana jest generyczna klasa List.

Klasy List<T> i ArrayListGeneryczna klasa List i niegeneryczna klasa ArrayList umożliwiają tworzenie tablic obiektów o dy-namicznym rozmiarze i należą do najczęściej używanych klas kolekcji. Klasa ArrayList implementujeinterfejs IList, podczas gdy List<T> implementuje zarówno IList, jak i IList<T> (jak również nowąwersję tylko do odczytu o nazwie IReadOnlyList<T>). Inaczej niż w przypadku tablic, wszystkieinterfejsy są zaimplementowane publicznie i zgodnie z oczekiwaniami metody takie jak Add czy Removesą dostępne.

Wewnętrznie klasy List<T> i ArrayList utrzymują tablicę obiektów, którą w razie osiągnięciamaksimum pojemności zamieniają na większą. Dodawanie elementów na końcu to efektywnaoperacja (ponieważ zazwyczaj na końcu jest wolne miejsce), natomiast wstawianie elementów w środ-ku pomiędzy innymi elementami może być powolne (ponieważ trzeba przesunąć wszystkie elementyznajdujące się za miejscem wstawiania). Jeśli chodzi o przeszukiwanie, to podobnie jak w przypadkutablic operacja jest efektywna, jeżeli przeprowadza się ją za pomocą metody BinarySearch na posorto-wanej liście. W innych sytuacjach wyszukiwanie jest mało wydajne, gdyż wymaga sprawdzenia każ-dego elementu po kolei.

Klasa List<T> jest do kilku razy szybsza od ArrayList, gdy T jest typem wartościo-wym, ponieważ List<T> nie wymaga pakowania ani odpakowywania elementów.

Klasy List<T> i ArrayList zawierają konstruktory przyjmujące istniejące kolekcje elementów —kopiują one wszystkie elementy z przekazanej kolekcji do nowej struktury:

public class List<T> : IList<T>, IReadOnlyList<T>{ public List (); public List (IEnumerable<T> collection); public List (int capacity);

Poleć książkęKup książkę

Page 31: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

Listy, kolejki, stosy i zbiory 309

// Add+Insert public void Add (T item); public void AddRange (IEnumerable<T> collection); public void Insert (int index, T item); public void InsertRange (int index, IEnumerable<T> collection);

// Remove public bool Remove (T item); public void RemoveAt (int index); public void RemoveRange (int index, int count); public int RemoveAll (Predicate<T> match);

// indeksowanie public T this [int index] { get; set; } public List<T> GetRange (int index, int count); public Enumerator<T> GetEnumerator();

// eksportowanie, kopiowanie i konwertowanie public T[] ToArray(); public void CopyTo (T[] array); public void CopyTo (T[] array, int arrayIndex); public void CopyTo (int index, T[] array, int arrayIndex, int count); public ReadOnlyCollection<T> AsReadOnly(); public List<TOutput> ConvertAll<TOutput> (Converter <T,TOutput> converter);

// inne public void Reverse(); // odwraca kolejno elementów listy public int Capacity { get;set; } // wymusza rozszerzenie wewn trznej tablicy public void TrimExcess(); // obcina wewn trzn tablic do potrzebnego rozmiaru public void Clear(); // usuwa wszystkie elementy, tak e Count=0}public delegate TOutput Converter <TInput, TOutput> (TInput input);

Oprócz tych składowych klasa List<T> zawiera egzemplarzowe wersje wszystkich metod przeszuki-wania i sortowania klasy Array.

Poniżej znajduje się przykład demonstrujący sposób użycia własności i metod klasy List. Przykładyprzeszukiwania i sortowania zamieściliśmy w podrozdziale „Klasa Array”.

List<string> words = new List<string>(); // nowa lista typu string

words.Add ("melon");words.Add ("awokado");words.AddRange (new[] { "banan", "pomara cza" } );words.Insert (0, "liczi"); // wstawianie na pocz tkuwords.InsertRange (0, new[] { "pomelo", "nashi" }); // wstawianie na pocz tku

words.Remove ("melon");words.RemoveAt (3); // usuni cie czwartego elementuwords.RemoveRange (0, 2); // usuni cie dwóch pierwszych elementów

// usuni cie wszystkich a cuchów zaczynaj cych si liter 'n'words.RemoveAll (s => s.StartsWith ("n"));

Console.WriteLine (words [0]); // pierwsze s owoConsole.WriteLine (words [words.Count - 1]); // ostatnie s owoforeach (string s in words) Console.WriteLine (s); // wszystkie s owaList<string> subset = words.GetRange (1, 2); // drugie i trzecie s owo

Poleć książkęKup książkę

Page 32: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

310 Rozdział 7. Kolekcje

string[] wordsArray = words.ToArray(); // tworzy now tablic typizowan

// kopiowanie pierwszych dwóch elementów na koniec istniej cej tablicystring[] existing = new string [1000];words.CopyTo (0, existing, 998, 2);

List<string> upperCastWords = words.ConvertAll (s => s.ToUpper());List<int> lengths = words.ConvertAll (s => s.Length);

Niegeneryczna klasa ArrayList jest wykorzystywana głównie ze względu na zgodność z kodem napi-sanym dla platformy 1.x. Używający jej programista musi się posługiwać niezręcznymi rzutowaniami,jak pokazano w poniższym przykładzie:

ArrayList al = new ArrayList();al.Add ("hello");string first = (string) al [0];string[] strArr = (string[]) al.ToArray (typeof (string));

Kompilator nie może zweryfikować takich operacji rzutowania, przez co np. poniższy kod przejdziekompilację i spowoduje awarię podczas wykonywania programu:

int first = (int) al [0]; // wyj tek wykonawczy

Klasa ArrayList pod względem funkcjonalności przypomina List<object>. Obieprzydają się, gdy potrzebna jest lista elementów różnego typu niemających wspólnegotypu bazowego (innego niż object). Klasa ArrayList może być lepszym wyborem,gdy podczas pracy z listą używa się refleksji (rozdział 19.). Techniki refleksji łatwiejjest stosować w odniesieniu do niegenerycznego typu ArrayList niż do typu generycz-nego List<object>.

Jeśli do programu zaimportuje się przestrzeń nazw System.Linq, to listę ArrayList można przekon-wertować na listę generyczną za pomocą metod Cast i ToList:

ArrayList al = new ArrayList();al.AddRange (new[] { 1, 5, 9 } );List<int> list = al.Cast<int>().ToList();

Cast i ToList to metody rozszerzeniowe klasy System.Linq.Enumerable.

Klasa LinkedList<T>Generyczna klasa LinkedList<T> stanowi implementację listy powiązanej dwustronnie (rysunek 7.4).Lista powiązana dwustronnie to łańcuch węzłów, w którym każdy węzeł zawiera referencję dopoprzedniego i następnego węzła oraz do samego siebie. Największą zaletą tej struktury jest to, żekażdy element można efektywnie wstawić w dowolnym miejscu listy, ponieważ wymaga to tylkoutworzenia nowego węzła i zaktualizowania kilku referencji. Jednak znalezienie miejsca do wsta-wienia elementu może być czasochłonne, ponieważ nie istnieje żaden mechanizm bezpośredniegoindeksowania takiej listy. Trzeba się przyjrzeć każdemu węzłowi i nie można korzystać z algorytmówwyszukiwania binarnego.

Poleć książkęKup książkę

Page 33: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

Listy, kolejki, stosy i zbiory 311

Rysunek 7.4. Klasa LinkedList<T>

Klasa LinkedList<T> implementuje interfejsy IEnumerable<T> i ICollection<T> (oraz ich niegene-ryczne wersje). Nie implementuje natomiast interfejsu IList<T>, ponieważ nie obsługuje dostępudo elementów za pomocą indeksów. Implementacja węzłów ma postać następującej klasy:

public sealed class LinkedListNode<T>{ public LinkedList<T> List { get; } public LinkedListNode<T> Next { get; } public LinkedListNode<T> Previous { get; } public T Value { get; set; }}

Nowy węzeł można dodać na pozycji określonej względem innego węzła lub na początku albo na koń-cu listy. W klasie LinkedList<T> znajdują się następujące metody do wykonywania takich operacji:

public void AddFirst(LinkedListNode<T> node);public LinkedListNode<T> AddFirst (T value);

public void AddLast (LinkedListNode<T> node);public LinkedListNode<T> AddLast (T value);

public void AddAfter (LinkedListNode<T> node, LinkedListNode<T> newNode);public LinkedListNode<T> AddAfter (LinkedListNode<T> node, T value);

public void AddBefore (LinkedListNode<T> node, LinkedListNode<T> newNode);public LinkedListNode<T> AddBefore (LinkedListNode<T> node, T value);

Istnieje też podobny zestaw metod do usuwania elementów:public void Clear();

public void RemoveFirst();public void RemoveLast();

public bool Remove (T value);public void Remove (LinkedListNode<T> node);

Poleć książkęKup książkę

Page 34: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

312 Rozdział 7. Kolekcje

Klasa LinkedList<T> zawiera też kilka wewnętrznych pól do rejestrowania liczby przechowywanychelementów oraz referencji do pierwszego i ostatniego elementu. Pola te są dostępne w postaci nastę-pujących publicznych własności:

public int Count { get; } // szybkiepublic LinkedListNode<T> First { get; } // szybkiepublic LinkedListNode<T> Last { get; } // szybkie

Dodatkowo klasa LinkedList<T> udostępnia następujące metody wyszukiwania (każda wymaga, abylista była wewnętrznie przeliczalna):

public bool Contains (T value);public LinkedListNode<T> Find (T value);public LinkedListNode<T> FindLast (T value);

Ponadto klasa LinkedList<T> obsługuje kopiowanie elementów do tablicy, aby można się byłoposługiwać indeksami, oraz umożliwia tworzenie enumeratorów, aby można się było posługiwaćpętlą foreach:

public void CopyTo (T[] array, int index);public Enumerator<T> GetEnumerator();

Oto przykład użycia klasy LinkedList<string>:var tune = new LinkedList<string>();tune.AddFirst ("do"); // dotune.AddLast ("sol"); // do - sol

tune.AddAfter (tune.First, "re"); // do - re - soltune.AddAfter (tune.First.Next, "mi"); // do - re - mi - soltune.AddBefore (tune.Last, "fa"); // do - re - mi - fa - sol

tune.RemoveFirst(); // re - mi - fa - soltune.RemoveLast(); // re - mi - fa

LinkedListNode<string> miNode = tune.Find ("mi");tune.Remove (miNode); // re - fatune.AddFirst (miNode); // mi - re - fa

foreach (string s in tune) Console.WriteLine (s);

Klasy Queue<T> i QueueKlasy Queue<T> i Queue to struktury danych typu FIFO (ang. first-in, first-out — pierwszy na wejściu,pierwszy na wyjściu) udostępniające m.in. metody Enqueue (do dodawania elementów na końcukolejki) i Dequeue (do pobierania i usuwania elementów z początku kolejki). Ponadto dostępnajest metoda Peek zwracająca element z początku struktury bez jego usuwania oraz własność Countumożliwiająca sprawdzenie przed zdejmowaniem elementów, czy jakieś w ogóle istnieją.

Choć kolejki są przeliczalne, nie implementują interfejsów IList<T> ani IList, ponieważ do skła-dowych nie można odwoływać się bezpośrednio za pomocą indeksów. W razie potrzeby dostępnajest jednak metoda ToArray służąca do kopiowania elementów do tablicy zapewniającej swobodnydostęp do swojej zawartości:

public class Queue<T> : IEnumerable<T>, ICollection, IEnumerable{

Poleć książkęKup książkę

Page 35: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

Listy, kolejki, stosy i zbiory 313

public Queue(); public Queue (IEnumerable<T> collection); // kopiuje istniej ce elementy public Queue (int capacity); // pozwala ograniczy automatyczne zmiany rozmiaru public void Clear(); public bool Contains (T item); public void CopyTo (T[] array, int arrayIndex); public int Count { get; } public T Dequeue(); public void Enqueue (T item); public Enumerator<T> GetEnumerator(); // aby mo na by o korzysta z p tli foreach public T Peek(); public T[] ToArray(); public void TrimExcess();}

Poniżej przedstawiamy przykład użycia klasy Queue<int>:var q = new Queue<int>();q.Enqueue (10);q.Enqueue (20);int[] data = q.ToArray(); // eksport zawarto ci do tablicyConsole.WriteLine (q.Count); // "2"Console.WriteLine (q.Peek()); // "10"Console.WriteLine (q.Dequeue()); // "10"Console.WriteLine (q.Dequeue()); // "20"Console.WriteLine (q.Dequeue()); // spowoduje zg oszenie wyj tku (pusta kolejka)

Wewnętrzna implementacja kolejek opiera się na tablicy, której rozmiar jest zmieniany zgodniez zapotrzebowaniem — podobną implementację ma generyczna klasa List. Kolejka utrzymujeindeksy wskazujące bezpośrednio na pierwszy i ostatni element, dzięki czemu operacje dokładaniai wyjmowania elementów są bardzo szybkie (z wyjątkiem sytuacji, gdy spowodują zmianę rozmiarustruktury).

Klasy Stack<T> i StackKlasy Stack<T> i Stack to struktury danych typu LIFO (ang. last-in, first-out — ostatni na wejściu,pierwszy na wyjściu) udostępniające m.in. metody Push (do dodawania elementu na wierzchu stosu)i Pop (do pobierania i usuwania elementów z wierzchu stosu). Dostępne są też niedestrukcyjnametoda Peek, jak również własność Count i metoda ToArray, umożliwiające eksport danych dostruktury pozwalającej na ich swobodne przeglądanie:

public class Stack<T> : IEnumerable<T>, ICollection, IEnumerable{ public Stack(); public Stack (IEnumerable<T> collection); // kopiuje istniej ce elementy public Stack (int capacity); // pozwala ograniczy automatyczne zmiany rozmiaru public void Clear(); public bool Contains (T item); public void CopyTo (T[] array, int arrayIndex); public int Count { get; } public Enumerator<T> GetEnumerator(); // aby mo na by o korzysta z p tli foreach public T Peek(); public T Pop(); public void Push (T item); public T[] ToArray(); public void TrimExcess();}

Poleć książkęKup książkę

Page 36: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

314 Rozdział 7. Kolekcje

Poniżej znajduje się przykład użycia klasy Stack<int>:var s = new Stack<int>();s.Push (1); // s = 1s.Push (2); // s = 1,2s.Push (3); // s = 1,2,3Console.WriteLine (s.Count); // drukuje 3Console.WriteLine (s.Peek()); // drukuje 3, s = 1,2,3Console.WriteLine (s.Pop()); // drukuje 3, s = 1,2Console.WriteLine (s.Pop()); // drukuje 2, s = 1Console.WriteLine (s.Pop()); // drukuje 1, s = <empty>Console.WriteLine (s.Pop()); // powoduje wyj tek

Wewnętrzna implementacja stosów bazuje na tablicy, której rozmiar zmienia się w razie potrzeby,podobnie jak w przypadku klas Queue<T> i List<T>.

Klasa BitArrayKlasa BitArray to kolekcja wartości typu bool z możliwością dynamicznej zmiany rozmiaru. Pozwalaefektywniej wykorzystać pamięć niż zwykła tablica lub struktura List wartości typu bool, ponieważdo przechowywania każdego elementu potrzebuje tylko jednego bitu, podczas gdy normalnie wartośćtypu bool zajmuje jeden bajt.

Indeksator struktury BitArray odczytuje i zapisuje pojedyncze bity:var bits = new BitArray(2);bits[1] = true;

Dostępne są cztery metody bitowe: And, Or, Xor oraz Not. Wszystkie oprócz ostatniej przyjmująobiekty typu BitArray:

bits.Xor (bits); // bitowe lub wykluczaj ce na samym sobieConsole.WriteLine (bits[1]); // fa sz

Klasy HashSet<T> i SortedSet<T>Klasy HashSet<T> i SortedSet<T> to generyczne kolekcje, które wprowadzono odpowiednio w .NETFramework 3.5 i 4.0. Obie wyróżniają się następującymi cechami:

Metody Contains charakteryzują się dużą szybkością działania dzięki posługiwaniu się algoryt-mem wyszukiwania wykorzystującym wartości skrótu.

Nie przechowują duplikatów i niepostrzeżenie ignorują żądania dodania elementów takich sa-mych jak elementy istniejące.

Nie ma możliwości odwołania się do elementu po jego pozycji.

Klasa SortedSet<T> przechowuje elementy w określonym porządku, a HashSet<T> nie przechowuje.

Wspólne cechy tych dwóch klas są dziełem implementacji interfejsu ISet<T>.

Z powodów historycznych klasa HashSet<T> znajduje się w zestawie System.Core.dll,a klasa SortedSet<T> i interfejs ISet<T> w zestawie System.dll.

Poleć książkęKup książkę

Page 37: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

Listy, kolejki, stosy i zbiory 315

Implementację klasy HashSet<T> stanowi tablica skrótów przechowująca tylko klucze. Natomiaststruktura SortedSet<T> jest zaimplementowana jako drzewo czerwono-czarne.

Obie kolekcje implementują interfejs ICollection<T> i udostępniają metody, jakich można się spo-dziewać, a więc np.: Contains, Add i Remove. Dodatkowo istnieje też wykorzystująca predykat metodaRemoveWhere do usuwania elementów.

Poniżej przedstawiamy przykład utworzenia zbioru HashSet<char> z istniejącej kolekcji, sprawdzenia,czy wybrany element jest dostępny w zbiorze, oraz jej przejrzenia (zwróć uwagę na usunięcieduplikatów):

var letters = new HashSet<char> ("gdyby kózka nie skaka a");

Console.WriteLine (letters.Contains ('g')); // prawdaConsole.WriteLine (letters.Contains ('j')); // fa sz

foreach (char c in letters) Console.Write (c); // gdyb kózanies

(Przekazanie obiektu typu string do konstruktora klasy HashSet<char> nie spowodowało błędu,ponieważ klasa string implementuje interfejs IEnumerable<char>).

Najciekawsze metody to te operujące na zbiorach. Poniższe metody mają charakter destrukcyjnyw tym sensie, że modyfikują zbiór:

public void UnionWith (IEnumerable<T> other); // dodajepublic void IntersectWith (IEnumerable<T> other); // usuwapublic void ExceptWith (IEnumerable<T> other); // usuwapublic void SymmetricExceptWith (IEnumerable<T> other); // usuwa

Natomiast te metody tylko sprawdzają coś w zbiorze, więc nie mają charakteru destrukcyjnego:public bool IsSubsetOf (IEnumerable<T> other);public bool IsProperSubsetOf (IEnumerable<T> other);public bool IsSupersetOf (IEnumerable<T> other);public bool IsProperSupersetOf (IEnumerable<T> other);public bool Overlaps (IEnumerable<T> other);public bool SetEquals (IEnumerable<T> other);

Metoda UnionWith dodaje wszystkie elementy z drugiego zbioru do pierwszego (wykluczając duplikaty).Metoda IntersectWith usuwa elementy, których nie ma w obu zbiorach. Z naszego zbioru znakówmożemy np. wydobyć wszystkie samogłoski w następujący sposób:

var letters = new HashSet<char> ("gdyby kózka nie skaka a");letters.IntersectWith ("aeioóuy");foreach (char c in letters) Console.Write (c); // yóaie

Metoda ExceptWith usuwa określone elementy ze zbioru źródłowego. W poniższym przykładzie pozba-wiamy nasz zbiór wszystkich samogłosek:

var letters = new HashSet<char> ("gdyby kózka nie skaka a");letters.ExceptWith ("aeioóu");foreach (char c in letters) Console.Write (c); // gdb kzns

Metoda SymmetricExceptWith usuwa wszystkie elementy oprócz tych, które występują tylko w jednymlub drugim zbiorze:

Poleć książkęKup książkę

Page 38: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

316 Rozdział 7. Kolekcje

var letters = new HashSet<char> ("gdyby kózka nie skaka a");letters.SymmetricExceptWith ("toby nogi nie z ama a");foreach (char c in letters) Console.Write (c); // dkóstom

Ponieważ klasy HashSet<T> i SortedSet<T> implementują interfejs IEnumerable<T>, ich metodyprzyjmują jako argumenty inne typy zbiorów (lub kolekcji).

Klasa SortedSet<T> ma wszystkie składowe klasy HashSet<T> oraz dodatkowo:public virtual SortedSet<T> GetViewBetween (T lowerValue, T upperValue)public IEnumerable<T> Reverse()public T Min { get; }public T Max { get; }

Ponadto konstruktor klasy SortedSet<T> opcjonalnie przyjmuje obiekt typu IComparer<T> (a nie kom-parator równości).

Oto jeden z efektów załadowania naszego przykładowego ciągu liter do zbioru SortedSet<char>:var letters = new SortedSet<char> ("gdyby kózka nie skaka a");foreach (char c in letters) Console.Write (c); // abdegiknsyzó

Teraz możemy pobrać wszystkie litery z przedziału od f do j:foreach (char c in letters.GetViewBetween ('f', 'j'))Console.Write (c); // gi

SłownikiSłownik jest kolekcją, w której każdy przechowywany element stanowi parę klucz – wartość. Tegotypu struktur danych najczęściej używa się do przeszukiwania i sortowania list.

Platforma .NET zawiera definicję standardowego protokołu słownikowego w postaci interfejsówIDictionary i IDictionary<TKey, TValue> oraz definicji kilku klas słownikowych ogólnego przezna-czenia. Różnią się one między sobą następującymi cechami:

niektóre sortują elementy, a inne nie;

niektóre pozwalają na dostęp do elementów wg pozycji (indeksu) i klucza, a inne nie;

niektóre są generyczne, a inne nie;

niektóre pozwalają na szybkie pobieranie elementów wg klucza dużych słowników, a inne nie.

W tabeli 7.1 przedstawiono zestawienie klas słownikowych i dzielących je różnic. Wartości czasowesą wyrażone w milisekundach dla 50 000 operacji na słowniku z kluczami i są wartościami całkowi-toliczbowymi wykonywanymi w komputerze PC z procesorem 1,5 GHz. (Różnice między generycz-nymi i niegenerycznymi wersjami wynikają z konieczności stosowania pakowania w jednym przy-padku i występują tylko w odniesieniu do typów wartościowych).

Poleć książkęKup książkę

Page 39: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

Słowniki 317

Tabela 7.1. Klasy słownikowe

Typ Strukturawewnętrzna

Indekso-wanie

Narzutpamię-ciowy(średnialiczbabajtów naelement)

Szybkość— losowewstawianie

Szybkość—wstawianiesekwen-cyjne

Szybkość—pobiera-nieelementówwg klucza

Niesortowane

Dictionary <K,V> Tablicaskrótów

Nie 22 30 30 20

Hashtable Tablicaskrótów

Nie 38 50 50 30

ListDictionary Listapowiązana

Nie 36 50 000 50 000 50 000

OrderedDictionary Tablicaskrótów +tablica

Tak 59 70 70 40

Sortowane

SortedDictionary<K,V>

Drzewoczerwono-czarne

Nie 20 130 100 120

SortedList <K,V> Dwie tablice Tak 2 3300 30 40

SortedList Dwie tablice Tak 27 4500 100 180

W notacji wielkiego O czasy pobierania elementów wg klucza wynoszą:

O(1) dla Hashtable, Dictionary oraz OrderedDictionary;

O(log n) dla SortedDictionary i SortedList;

O(n) dla ListDictionary (i typów niesłownikowych, takich jak List<T>).

Parametr n reprezentuje liczbę elementów w kolekcji.

Interfejs IDictionary<TKey,TValue>Interfejs IDictionary<TKey,TValue> to standardowy protokół dla wszystkich kolekcji przechowują-cych pary klucz – wartość. Stanowi on rozszerzenie interfejsu ICollection<T>, do którego dodajemetody i własności umożliwiające dostęp do elementów na podstawie kluczy dowolnego typu:

public interface IDictionary <TKey, TValue> : ICollection <KeyValuePair <TKey, TValue>>, IEnumerable{ bool ContainsKey (TKey key); bool TryGetValue (TKey key, out TValue value); void Add (TKey key, TValue value); bool Remove (TKey key);

Poleć książkęKup książkę

Page 40: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

318 Rozdział 7. Kolekcje

TValue this [TKey key] { get; set; } // g ówny indeksator — wg klucza ICollection <TKey> Keys { get; } // zwraca tylko klucze ICollection <TValue> Values { get; } // zwraca tylko warto ci}

W .NET Framework 4.5 dodano interfejs o nazwie IReadOnlyDictionary<TKey,TValue> definiujący podzbiór składowych słownika tylko do odczytu. Odpowiada

on typowi IMapView<K,V> Windows Runtime i został wprowadzony głównie jakojego odpowiednik.

Aby dodać element do słownika, należy wywołać metodę Add albo użyć metody dostępowej indeksu— ta druga dodaje element do słownika, jeśli nie ma w nim jeszcze takiego klucza (a jeśli jest, todokonuje modyfikacji elementu). W żadnej implementacji słownika nie może się powtórzyć ani jedenklucz, więc dwukrotne wywołanie metody Add z takim samym kluczem powoduje wyjątek.

Aby pobrać element ze słownika, należy się posłużyć indeksatorem albo metodą TryGetValue. Jeżelidany klucz nie istnieje, indeksator zgłasza wyjątek, podczas gdy metoda TryGetValue zwraca fałsz.Istnienie elementu w strukturze można sprawdzić za pomocą metody ContainsKey. Jeśli jednakpóźniej dany element trzeba pobrać, będzie to oznaczało konieczność wykonania dwóch takichsamych operacji wyszukiwania.

Operacja enumeracji struktury typu IDictionary<TKey,TValue> zwraca sekwencję struktur KeyValuePair:public struct KeyValuePair <TKey, TValue>{ public TKey Key { get; } public TValue Value { get; }}

Istnieje możliwość przeglądania tylko kluczy lub tylko wartości przy użyciu własności Keys i Values.

W następnej sekcji przedstawiamy przykład użycia tego interfejsu w połączeniu z generyczną klasąDictionary.

Interfejs IDictionaryNiegeneryczny interfejs IDictionary jest bardzo podobny do generycznego IDictionary<TKey,TValue>,ale różni się od niego w dwóch ważnych aspektach. Należy wiedzieć o tych różnicach, ponieważinterfejs IDictionary występuje w starym kodzie (włącznie z samą platformą .NET Framework):

Próba pobrania przez indeksator nieistniejącego klucza kończy się zwróceniem wartości null(a nie wyjątkiem).

Do sprawdzania, czy dany element znajduje się w strukturze, służy metoda Contains, a nieContainsKey.

Efektem przeliczania niegenerycznego IDictionary jest zwrot sekwencji struktur DictionaryEntry:public struct DictionaryEntry{ public object Key { get; set; } public object Value { get; set; }}

Poleć książkęKup książkę

Page 41: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

Słowniki 319

Klasy Dictionary<TKey,TValue> i HashtableGeneryczna klasa Dictionary należy do najczęściej używanych kolekcji (obok List<T>). Do przecho-wywania kluczy i wartości wykorzystuje tablicę skrótów (ang. hashtable), dzięki czemu jest szybkai efektywna.

Niegeneryczna wersja klasy Dictionary<TKey,TValue> nazywa się Hashtable. Nieistnieje niegeneryczna klasa o nazwie Dictionary. Dlatego pisząc Dictionary,mamy na myśli generyczną klasę Dictionary<TKey,TValue>.

Klasa Dictionary implementuje zarówno generyczny, jak i niegeneryczny interfejs IDictionary,przy czym generyczna wersja jest udostępniona publicznie. W istocie Dictionary to „podręcznikowa”implementacja generycznego interfejsu IDictionary.

Oto przykład jej użycia:var d = new Dictionary<string, int>();

d.Add("Jeden", 1);d["Dwa"] = 2; // dodaje element do s ownika, poniewa nie ma w nim jeszcze "dwa"d["Dwa"] = 22; // modyfikuje s ownik, poniewa "dwa" ju w nim jestd["Trzy"] = 3;

Console.WriteLine (d["Dwa"]); // drukuje "22"Console.WriteLine (d.ContainsKey ("Jeden")); // prawda (szybka operacja)Console.WriteLine (d.ContainsValue (3)); // prawda (wolna operacja)int val = 0;if (!d.TryGetValue ("jedeN", out val)) Console.WriteLine ("Brak"); // "Brak" (wielko liter ma znaczenie)

// trzy ró ne sposoby przegl dania s ownika:

foreach (KeyValuePair<string, int> kv in d) // Jeden; 1 Console.WriteLine (kv.Key + "; " + kv.Value); // Dwa; 22 // Trzy; 3

foreach (string s in d.Keys) Console.Write (s); // JedenDwaTrzyConsole.WriteLine();foreach (int i in d.Values) Console.Write (i); // 1223

Wewnętrzna tablica skrótów konwertuje klucz każdego elementu na całkowitoliczbową wartośćskrótu, która jest pseudoniepowtarzalna, a następnie za pomocą specjalnego algorytmu konwertujeten skrót na klucz mieszający. Wewnętrznie za pomocą tego klucza wybierany jest „kubełek”, doktórego należy dany wpis. Jeśli kubełek zawiera więcej niż jedną wartość, to jest przeszukiwany algo-rytmem liniowym. Dobra funkcja mieszająca nie dąży do zwracania wyłącznie niepowtarzalnychskrótów (co w większości przypadków byłoby niemożliwe), tylko do równomiernego rozmieszczeniaskrótów w 32-bitowej przestrzeni całkowitoliczbowej. W ten sposób unika się groźby powstaniabardzo małej liczby bardzo dużych (i nieefektywnych) kubełków.

Klucze w słowniku mogą być każdego typu, pod warunkiem że można je porównywać i tworzyćz nich wartości skrótu. Domyślnie klucze porównuje się za pomocą metody klucza object.Equals,a pseudoniepowtarzalna wartość skrótu jest obliczana przez metodę klucza GetHashCode. Możnato zmienić przez przesłonięcie tych metod lub dostarczenie obiektu implementującego interfejs

Poleć książkęKup książkę

Page 42: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

320 Rozdział 7. Kolekcje

IEqualityComparer podczas tworzenia słownika. Możliwość tę wykorzystuje się często, gdy stoso-wane są klucze łańcuchowe w celu użycia komparatora nierozróżniającego wielkości liter:

var d = new Dictionary<string, int> (StringComparer.OrdinalIgnoreCase);

Szerzej na ten temat piszemy jeszcze w podrozdziale „Dołączanie protokołów równości i porządko-wania”.

Tak jak w przypadku wszystkich innych typów kolekcji, wydajność słownika można nieco podnieśćprzez określenie w konstruktorze oczekiwanego rozmiaru struktury, co pozwala ograniczyć potrzebęwykonywania operacji zmiany rozmiaru (lub w ogóle jej uniknąć).

Niegeneryczna wersja nazywa się Hashtable i pod względem funkcjonalnym jest podobna do gene-rycznej, tylko udostępnia niegeneryczny interfejs IDictionary, o którym była mowa wcześniej.

Wadą klas Dictionary i Hashtable jest to, że nie sortują przechowywanych elementów. Nie zachowująnawet kolejności dodawania wpisów. Jak wszystkie słowniki, struktury te nie pozwalają na zapisaniedwóch takich samych kluczy.

Gdy w .NET Framework 2.0 wprowadzono generyczne kolekcje, programiści CLRpostanowili nadać im nazwy zgodne z tym, co reprezentują (Dictionary, List), a nieodnoszące się do ich wewnętrznej implementacji (Hashtable, ArrayList). Choćjest to dobra decyzja, dzięki której w przyszłości będzie można bez przeszkód zmieniaćpodstawową implementację, wybrane nazwy nie pozwalają się zorientować, jakąwydajnością (a informacja ta jest często najważniejszym kryterium wyboru) charakte-ryzują się poszczególne kolekcje.

Klasa OrderedDictionaryOrderedDictionary to niegeneryczny słownik przechowujący elementy w kolejności ich dodawania.W tej strukturze elementy dostępne są zarówno wg indeksu, jak i wg klucza.

OrderedDictionary nie jest słownikiem posortowanym.

Klasa OrderedDictionary jest kombinacją klas Hashtable i ArrayList, tzn. zawiera całą funkcjonalnośćpierwszej i kilka dodatkowych funkcji, takich jak RemoveAt i indeksator całkowitoliczbowy. Ponadtostruktura ta udostępnia własności Keys i Values zwracające elementy w pierwotnym porządku.

Klasę tę wprowadzono w .NET 2.0, ale wciąż nie wiadomo dlaczego nie ma jej wersji generycznej.

Klasy ListDictionary i HybridDictionaryKlasa ListDictionary przechowuje dane w liście powiązanej jednostronnie. Nie sortuje elementów,ale zapisuje je w kolejności dodawania. Struktura ta działa bardzo wolno, gdy jest duża. Jedyny sensjej istnienia to wysoka wydajność dla bardzo małych list (zawierających mniej niż dziesięć elementów).

Klasa HybridDictionary to ListDictionary automatycznie konwertująca się na Hashtable po osią-gnięciu określonego rozmiaru w celu uniknięcia problemów wydajnościowych. Chodzi o to, by jak

Poleć książkęKup książkę

Page 43: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

Słowniki 321

najoszczędniej operować pamięcią, gdy słownik jest mały, oraz by zachować dobrą wydajność,kiedy się powiększy. Biorąc jednak pod uwagę czas potrzebny na przeprowadzenie konwersji —oraz to, że klasa Dictionary też nie jest zbyt ciężka ani wolna — nikomu nie zaszkodzi użycie słownikaDictionary w zamian.

Obie te klasy występują tylko w wersji niegenerycznej.

Słowniki sortowanePlatforma .NET zawiera dwie klasy słownikowe o wewnętrznej strukturze sprawiającej, że ich zawar-tość jest zawsze posortowana wg klucza:

SortedDictionary<TKey,TValue>,

SortedList<TKey,TValue>1.

(W tej sekcji skracamy zapis <TKey,TValue> do postaci <,>).

Implementacja klasy SortedDictionary<,> bazuje na drzewie czerwono-czarnym — strukturzedanych, która charakteryzuje się taką samą wydajnością w każdej operacji wstawiania i pobieraniaelementu.

Implementację klasy SortedList<,> stanowi uporządkowana para tablic, co zapewnia szybkie pobie-ranie danych (za pomocą binarnego algorytmu wyszukiwania), ale mało efektywne wstawianieelementów (ponieważ trzeba przesunąć istniejące elementy, aby zrobić miejsce dla dodawanego).

Klasa SortedDictionary<,> jest znacznie szybsza od SortedList<,> we wstawianiu elementów w loso-wej kolejności (zwłaszcza gdy struktura danych jest duża). Za to SortedList<,> dodatkowo umożliwiaodnoszenie się do elementów wg indeksu lub wg klucza. Mając posortowaną listę, można bezpo-średnio przejść do n-tego elementu sekwencji (posługując się indeksatorem lub własnościami Keysi Values). Aby zrobić to samo ze strukturą SortedDictionary<,>, należy ręcznie przejrzeć n elemen-tów. (Ewentualnie można napisać klasę łączącą posortowany słownik z listą).

Żadna z tych trzech kolekcji nie pozwala na duplikowanie kluczy (tak jest we wszystkich słownikach).

Poniżej przedstawiamy przykład, w którym za pomocą refleksji ładujemy wszystkie metody zdefinio-wane w klasie System.Object do posortowanej listy, w której klucze stanowią nazwy metod, a następnieprzeglądamy te klucze i ich wartości:

// MethodInfo znajduje si w przestrzeni nazw System.Reflection

var sorted = new SortedList <string, MethodInfo>();

foreach (MethodInfo m in typeof (object).GetMethods()) sorted [m.Name] = m;

foreach (string name in sorted.Keys) Console.WriteLine (name);

foreach (MethodInfo m in sorted.Values) Console.WriteLine (m.Name + " zwraca obiekt typu " + m.ReturnType);

1 stnieje też identyczna pod względem funkcjonalności niegeneryczna wersja o nazwie SortedList.

Poleć książkęKup książkę

Page 44: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

322 Rozdział 7. Kolekcje

Oto wynik pierwszego przeglądu:EqualsGetHashCodeGetTypeReferenceEqualsToString

A to jest wynik drugiej pętli:Equals zwraca obiekt typu System.BooleanGetHashCode zwraca obiekt typu System.Int32GetType zwraca obiekt typu System.TypeReferenceEquals zwraca obiekt typu System.BooleanToString zwraca obiekt typu System.String

Zauważ, że zawartość wstawiliśmy do słownika za pomocą indeksatora. Gdybyśmy zamiast niegoużyli metody Add, zgłosiłaby wyjątek, ponieważ klasa object, której dotyczy stosowana przez nas re-fleksja, przeciąża metodę Equals, a do słownika nie można dodać dwa razy takiego samego klucza.Dzięki użyciu indeksatora drugi wpis po prostu zastąpi poprzedni i nie wystąpi żaden błąd.

Jeśli trzeba zapisać kilka elementów pod takim samym kluczem, to elementy wartościmożna zdefiniować jako listy:SortedList <string, List<MethodInfo>>

Wracając do naszego przykładu: poniższa instrukcja pobiera obiekt MethodInfo, którego klucz toGetHashCode. Dokładnie tak samo pracowalibyśmy ze zwykłym słownikiem:

Console.WriteLine (sorted ["GetHashCode"]); // Int32 GetHashCode()

Wszystko, co do tej pory zrobiliśmy, dałoby się wykonać także z klasą SortedDictionary<,>. Aleponiższe dwa wiersze kodu zadziałają tylko z listą posortowaną, ponieważ pobieramy w nich ostatniklucz i ostatnią wartość:

Console.WriteLine (sorted.Keys [sorted.Count - 1]); // ToStringConsole.WriteLine (sorted.Values[sorted.Count - 1].IsVirtual); // prawda

Kolekcje i pośredniki z możliwością dostosowywaniaOpisane w poprzednich podrozdziałach klasy kolekcji są wygodne w użyciu, ponieważ można bezpo-średnio tworzyć ich egzemplarze. Niestety, nie ma możliwości kontrolowania sposobu dodawaniaani usuwania elementów. Możliwość taka jest jednak potrzebna w aplikacjach, w których używanesą ściśle typizowane kolekcje, np.:

aby uruchomić zdarzenie w reakcji na dodanie lub usunięcie elementu;

aby zaktualizować własności z powodu dodania lub usunięcia elementu;

aby wykryć „niedozwoloną” operację dodawania lub usuwania i zgłosić wyjątek (gdy np. operacjałamie jakieś zasady biznesowe).

Platforma .NET Framework zawiera klasy kolekcji przeznaczone do użytku właśnie w takich sytu-acjach. Znajdują się one w przestrzeni nazw System.Collections.ObjectModel i tak naprawdę są

Poleć książkęKup książkę

Page 45: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

Kolekcje i pośredniki z możliwością dostosowywania 323

pośrednikami lub opakowaniami implementującymi interfejs IList<T> lub IDictionary<,> przezprzekazywanie metod do podstawowej kolekcji. Każda operacja Add, Remove i Clear zostaje przekiero-wana przez metodę wirtualną, która po przesłonięciu stanowi rodzaj „bramy”.

Klasy kolekcji z możliwością dostosowywania są powszechnie wykorzystywane do tworzenia publicz-nie dostępnych kolekcji, takich jak np. kolekcja kontrolek publicznych klasy System.Windows.Form.

Klasy Collection<T> i CollectionBaseKlasa Collection<T> to modyfikowalne opakowanie klasy List<T>.

Implementuje ona interfejsy IList<T> i IList oraz definiuje cztery dodatkowe metody wirtualnei chronioną własność:

public class Collection<T> : IList<T>, ICollection<T>, IEnumerable<T>, IList, ICollection, IEnumerable{ // ... protected virtual void ClearItems(); protected virtual void InsertItem (int index, T item); protected virtual void RemoveItem (int index); protected virtual void SetItem (int index, T item);

protected IList<T> Items { get; }}

Metody wirtualne stanowią bramę, przez którą można „się podpiąć”, aby zmienić lub rozszerzyćnormalną funkcjonalność listy. Chroniona własność Items umożliwia implementatorowi uzyskaniebezpośredniego dostępu do „wewnętrznej listy” — w ten sposób można dokonywać zmian wewnątrzbez uruchamiania metod wirtualnych.

Metody wirtualne nie muszą być przesłonięte. Można je zostawić nietknięte, aż nadejdzie potrzebamodyfikacji domyślnego działania listy. Poniżej znajduje się schematyczny przykład ilustrującytypowy sposób użycia klasy Collection<T>:

public class Animal{ public string Name; public int Popularity;

public Animal (string name, int popularity) { Name = name; Popularity = popularity; }}

public class AnimalCollection : Collection <Animal>{ // AnimalCollection to ju w pe ni funkcjonalna lista zwierz t. // Nie jest potrzebny aden dodatkowy kod.}

public class Zoo // klasa, która b dzie udost pnia AnimalCollection,{ // normalnie zawiera aby dodatkowe sk adowe public readonly AnimalCollection Animals = new AnimalCollection();}

Poleć książkęKup książkę

Page 46: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

324 Rozdział 7. Kolekcje

class Program{ static void Main() { Zoo zoo = new Zoo(); zoo.Animals.Add (new Animal ("Kangur", 10)); zoo.Animals.Add (new Animal ("Król Lew", 20)); foreach (Animal a in zoo.Animals) Console.WriteLine (a.Name); }}

W tej postaci klasa AnimalCollection nie przewyższa funkcjonalnością prostej klasy List<Animal>,ponieważ została stworzona tylko po to, by można ją było w przyszłości rozszerzyć. Dla przykładudo klasy Animal dodamy teraz własność Zoo, aby można było określić, w którym zoo mieszka danezwierzę, i dodatkowo przesłonimy wszystkie metody wirtualne klasy Collection<Animal>, aby za-pewnić automatyczną obsługę tej własności:

public class Animal{ public string Name; public int Popularity; public Zoo Zoo { get; internal set; } public Animal(string name, int popularity) { Name = name; Popularity = popularity; }}

public class AnimalCollection : Collection <Animal>{ Zoo zoo; public AnimalCollection (Zoo zoo) { this.zoo = zoo; } protected override void InsertItem (int index, Animal item) { base.InsertItem (index, item); item.Zoo = zoo; } protected override void SetItem (int index, Animal item) { base.SetItem (index, item); item.Zoo = zoo; } protected override void RemoveItem (int index) { this [index].Zoo = null; base.RemoveItem (index); } protected override void ClearItems() { foreach (Animal a in this) a.Zoo = null; base.ClearItems(); }}

public class Zoo{ public readonly AnimalCollection Animals; public Zoo() { Animals = new AnimalCollection (this); }

Poleć książkęKup książkę

Page 47: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

Kolekcje i pośredniki z możliwością dostosowywania 325

Klasa Collection<T> zawiera też konstruktor przyjmujący obiekty implementujące interfejs IList<T>.Jednak inaczej niż jest w przypadku innych klas kolekcji, przekazana lista nie zostanie skopiowana,tylko nowy egzemplarz klasy Collection<T> będzie pośrednikiem do opakowywanej listy, więcwszelkie wprowadzane w niej zmiany będą widoczne przez tego pośrednika (choć bez uruchamianiametod wirtualnych klasy Collection<T>).

Klasa CollectionBase

Klasa CollectionBase to niegeneryczna wersja klasy Collection<T>, którą wprowadzono w wersji1.0 platformy. Zapewnia bardzo podobną funkcjonalność jak Collection<T>, tylko jest mniej wygodnaw użyciu. Zamiast szablonowych metod: InsertItem, RemoveItem, SetItem i ClearItem, klasa CollectionBase zawiera metody „zaczepowe”, które podwajają tylko zestaw potrzebnych metod: OnInsert,

OnInsertComplete, OnSet, OnSetComplete, OnRemove, OnRemoveComplete, OnClear oraz OnClearComplete.Jako że klasa CollectionBase nie jest generyczna, tworząc jej podklasę, należy dodatkowo zaimple-mentować metody typizowane — przynajmniej indeksator i metodę Add.

Klasy KeyedCollection<TKey,TItem> i DictionaryBaseKlasa KeyedCollection<TKey,TItem> jest podklasą klasy Collection<TItem>. W pewnych obszarachrozszerza jej funkcjonalność, a w innych ogranicza. Jeśli chodzi o rozszerzenia, to dodaje możliwośćodnoszenia się do elementów wg klucza, tak jak w słownikach. Likwiduje natomiast możliwośćtworzenia pośredników listy wewnętrznej.

Kolekcja KeyedCollection przypomina w pewnym stopniu klasę OrderedDictionary, ponieważtakże jest kombinacją liniowej listy i tablicy skrótów. Jednak w odróżnieniu od niej nie implementujeinterfejsu IDictionary i nie rozpoznaje pojęcia pary klucz – wartość. Klucze są tworzone z samychelementów przez abstrakcyjną metodę GetKeyForItem. Oznacza to, że kolekcję taką można przeglądaćw taki sam sposób jak zwykłą listę.

Klasę KeyedCollection<TKey,TItem> można traktować jak Collection<TItem> z szybkim wyszukiwa-niem po kluczach.

Jako że jest ona podklasą klasy Collection<>, dziedziczy wszystkie jej składniki z wyjątkiem możli-wości podawania istniejącej listy konstruktorowi. Dodatkowe składowe, jakie definiuje, to:

public abstract class KeyedCollection <TKey, TItem> : Collection <TItem>

// ...

protected abstract TKey GetKeyForItem(TItem item); protected void ChangeItemKey(TItem item, TKey newKey);

// szybkie wyszukiwanie wg klucza to dodatek do wyszukiwania indeksowego public TItem this[TKey key] { get; }

protected IDictionary<TKey, TItem> Dictionary { get; }}

Metodę GetKeyForItem należy przesłonić tak, aby prawidłowo obliczała klucze elementów utworzo-nego obiektu. Metodę ChangeItemKey należy wywołać, jeżeli zmieni się własność przechowującaklucz elementu, aby zaktualizować słownik wewnętrzny. Własność Dictionary zwraca wewnętrzny

Poleć książkęKup książkę

Page 48: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

326 Rozdział 7. Kolekcje

słownik wykorzystywany do wyszukiwania, tworzony w chwili dodania pierwszego elementu. W raziepotrzeby można zmienić tę zasadę w konstruktorze tak, aby utworzenie słownika następowałodopiero po przekroczeniu pewnego progu (do tego czasu elementy są wyszukiwane liniowo). Dobrympowodem do tego, by nie określać progu utworzenia słownika, jest to, że może on być przydatnydo utworzenia kolekcji ICollection<> kluczy przy użyciu własności Keys klasy Dictionary.

Klasy KeyedCollection<,> najczęściej używa się do tworzenia kolekcji elementów dostępnych poprzezindeksy i nazwy. W ramach przykładu zaimplementujemy naszą klasę AnimalCollection jakoKeyedCollection<string,Animal>:

public class Animal{ string name; public string Name { get { return name; } set { if (Zoo != null) Zoo.Animals.NotifyNameChange (this, value); name = value; } } public int Popularity; public Zoo Zoo { get; internal set; }

public Animal (string name, int popularity) { Name = name; Popularity = popularity; }}

public class AnimalCollection : KeyedCollection <string, Animal>{ Zoo zoo; public AnimalCollection (Zoo zoo) { this.zoo = zoo; }

internal void NotifyNameChange (Animal a, string newName) { this.ChangeItemKey (a, newName); }

protected override string GetKeyForItem (Animal item) { return item.Name; }

// poni sze metody by yby zaimplementowane, jak w poprzednim przyk adzie protected override void InsertItem (int index, Animal item)... protected override void SetItem (int index, Animal item)... protected override void RemoveItem (int index)... protected override void ClearItems()...}

public class Zoo{ public readonly AnimalCollection Animals; public Zoo() { Animals = new AnimalCollection (this); }}

Poleć książkęKup książkę

Page 49: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

Kolekcje i pośredniki z możliwością dostosowywania 327

class Program{ static void Main() { Zoo zoo = new Zoo(); zoo.Animals.Add (new Animal ("Kangur", 10)); zoo.Animals.Add (new Animal ("Król Lew", 20)); Console.WriteLine (zoo.Animals [0].Popularity); // 10 Console.WriteLine (zoo.Animals ["Mr Sea Lion"].Popularity); // 20 zoo.Animals ["Kangaroo"].Name = "Mr Roo"; Console.WriteLine (zoo.Animals ["Mr Roo"].Popularity); // 10 }}

DictionaryBase

DictionaryBase to niegeneryczna wersja klasy KeyedCollection. Jest to stara klasa, którą zbudowanow całkiem odmienny sposób niż nowsze — implementuje interfejs IDictionary i podobnie jakCollectionBase wykorzystuje nieporęczne metody zaczepowe: OnInsert, OnInsertComplete, OnSet,OnSetComplete, OnRemove, OnRemoveComplete, OnClear oraz OnClearComplete (i dodatkowo OnGet).Największą zaletą implementacji słownika IDictionary zamiast stosowania podejścia klasy KeyedCollection jest to, że nie trzeba tworzyć podklasy, aby uzyskać klucze. Ponieważ jednak klasa

DictionaryBase istnieje przede wszystkim po to, by utworzyć jej podklasę, ta zaleta nie ma znaczenia.Ulepszony model klasy KeyedCollection z pewnością powstał dlatego, że klasa ta została napisanakilka lat później, kiedy programiści mogli spojrzeć na nią z pewnej perspektywy. Dlatego też klasęDictionaryBase należy traktować głównie jako środek do zapewnienia zgodności ze starym kodem.

Klasa ReadOnlyCollection<T>Klasa ReadOnlyCollection<T> jest opakowaniem, albo pośrednikiem, zapewniającym widok tylko doodczytu kolekcji. Jest przydatna, gdy klasa ma publicznie udostępnić kolekcję, której nie możnamodyfikować z zewnątrz, a którą można zmieniać wewnętrznie.

Kolekcja tylko do odczytu przyjmuje kolekcję wejściową w konstruktorze, do którego ma stałą refe-rencję. Nie tworzy ona statycznej kopii przekazanej kolekcji, więc wszelkie późniejsze zmiany kolekcjiwejściowej są widoczne przez opakowanie.

W ramach przykładu powiedzmy, że chcemy utworzyć klasę publicznie udostępniającą listę łańcu-chów tylko do odczytu o nazwie Names:

public class Test{ public List<string> Names { get; private set; }}

To dopiero połowa pracy. Choć inne typy nie mogą nic przypisać do własności Names, nadal mogąwywoływać na liście metody Add, Remove i Clear. Rozwiązaniem problemu jest klasa ReadOnlyCollection<T>:public class Test{ List<string> names; public ReadOnlyCollection<string> Names { get; private set; }

Poleć książkęKup książkę

Page 50: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

328 Rozdział 7. Kolekcje

public Test() { names = new List<string>(); Names = new ReadOnlyCollection<string> (names); }

public void AddInternally() { names.Add ("test"); }}

Teraz tylko składowe klasy Test mogą zmieniać listę nazw:Test t = new Test();

Console.WriteLine (t.Names.Count); // 0t.AddInternally();Console.WriteLine (t.Names.Count); // 1

t.Names.Add ("test"); // b d kompilacji((IList<string>) t.Names).Add ("test"); // NotSupportedException

Dołączanie protokołów równości i porządkowaniaW podrozdziałach „Sprawdzanie równości” i „Określanie kolejności” w rozdziale 6. opisaliśmy stan-dardowe protokoły platformy .NET umożliwiające porównywanie typów i obliczanie ich skrótów.Typ implementujący te protokoły może prawidłowo funkcjonować w słowniku i liście posortowanejbez żadnego dodatkowego przygotowania. Mówiąc konkretniej:

Typ, dla którego metody Equals i GetHashCode zwracają sensowne wyniki, może być wykorzysty-wany jako klucz w strukturach Dictionary i Hashtable.

Typ implementujący interfejsy IComparable i IComparable<T> może być używany jako klucz wewszystkich sortowanych słownikach i listach.

Domyślna implementacja operacji sprawdzania równości i porównywania typu zazwyczaj odzwier-ciedla jego „naturalne” cechy. Ale programiście nie zawsze zależy na domyślnym znaczeniu tychoperacji. Czasami potrzebny jest np. słownik, w którym klucze są typu string i nie ma znaczeniawielkość liter. Innym razem ktoś może potrzebować listy klientów posortowanej wg kodów poczto-wych. Dlatego na platformie .NET Framework stworzono dodatkowy zestaw protokołów „dołącza-nych” o dwojakim przeznaczeniu:

Dzięki nim można włączać alternatywne sposoby określania równości i kolejności elementów.

Umożliwiają korzystanie ze słowników lub posortowanych kolekcji z typem kluczy, które w swejistocie nie są porównywalne.

Protokoły dołączane obejmują następujące interfejsy:

IEqualityComparer i IEqualityComparer<T>

Odpowiada za sprawdzanie równości i obliczanie skrótów.

Rozpoznawany przez Hashtable i Dictionary.

Poleć książkęKup książkę

Page 51: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

Dołączanie protokołów równości i porządkowania 329

IComparer i IComparer<T>

Odpowiada za porównywanie pod względem kolejności.

Rozpoznawany przez słowniki i kolekcje posortowane; także Array.Sort.

Każdy interfejs występuje w wersji generycznej i niegenerycznej. Dodatkowo interfejsy IEqualityComparer mają domyślną implementację w klasie o nazwie EqualityComparer.

Ponadto w .NET Framework 4.0 dodano dwa nowe interfejsy: IStructuralEquatable i IStructuralComparable, które umożliwiają wykonywanie porównań strukturalnych na klasach i tablicach.

IEqualityComparer i EqualityComparerInterfejs IEqualityComparer włącza niestandardowe operacje sprawdzania równości i obliczaniaskrótów i jest przeznaczony głównie do pracy z klasami Dictionary i Hashtable.

Przypomnimy pokrótce wymagania, jakie powinien spełniać słownik skrótów. Dla każdego kluczamusi odpowiadać na dwa pytania:

Czy jest taki sam jak inny?

Jaka jest jego całkowitoliczbowa wartość skrótu?

Komparator sprawdzający równość odpowiada na te pytania przez implementację interfejsówIEqualityComparer:

public interface IEqualityComparer<T>{ bool Equals (T x, T y); int GetHashCode (T obj);}

public interface IEqualityComparer // wersja niegeneryczna{ bool Equals (object x, object y); int GetHashCode (object obj);}

Aby napisać własny komparator, należy zaimplementować jeden z tych interfejsów lub oba (imple-mentacja obu zapewnia największą elastyczność). Ponieważ jednak jest to dość czasochłonne zajęcie,ewentualnie można też utworzyć podklasę abstrakcyjnej klasy EqualityComparer, której definicjawygląda następująco:

public abstract class EqualityComparer<T> : IEqualityComparer, IEqualityComparer<T>{ public abstract bool Equals (T x, T y); public abstract int GetHashCode (T obj);

bool IEqualityComparer.Equals (object x, object y); int IEqualityComparer.GetHashCode (object obj);

public static EqualityComparer<T> Default { get; }}

Klasa EqualityComparer implementuje oba interfejsy, więc programiście pozostaje już tylko prze-słonięcie dwóch abstrakcyjnych metod.

Poleć książkęKup książkę

Page 52: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

330 Rozdział 7. Kolekcje

Semantyka metod Equals i GetHashCode jest taka sama jak metod object.Equals i object.GetHashCodeopisanych w rozdziale 6. W poniższym przykładzie definiujemy klasę Customer z dwoma polamii piszemy komparator porównujący imiona i nazwiska:

public class Customer{ public string LastName; public string FirstName;

public Customer (string last, string first) { LastName = last; FirstName = first; }}public class LastFirstEqComparer : EqualityComparer <Customer>{ public override bool Equals (Customer x, Customer y) => x.LastName == y.LastName && x.FirstName == y.FirstName;

public override int GetHashCode (Customer obj) => (obj.LastName + ";" + obj.FirstName).GetHashCode();}

Aby pokazać, jak to działa, utworzymy dwóch klientów:Customer c1 = new Customer ("Bara ski", "Jan");Customer c2 = new Customer ("Bara ski", "Jan");

Jako że nie przesłoniliśmy metody object.Equals, zastosowanie ma normalna semantyka refe-rencyjna:

Console.WriteLine (c1 == c2); // fa szConsole.WriteLine (c1.Equals (c2)); // fa sz

To samo dzieje się, gdy użyjemy naszych obiektów w słowniku, nie określając własnego komparatora:var d = new Dictionary<Customer, string>();d [c1] = "Jan";Console.WriteLine (d.ContainsKey (c2)); // fa sz

A teraz podajemy własny komparator:var eqComparer = new LastFirstEqComparer();var d = new Dictionary<Customer, string> (eqComparer);d [c1] = "Jan";Console.WriteLine (d.ContainsKey (c2)); // prawda

W tym przypadku musielibyśmy uważać, aby nie zmienić pól FirstName ani LastName klienta pod-czas używania obiektu w słowniku. W przeciwnym razie zmieniłaby się wartość skrótu i słownikprzestałby działać.

Metoda EqualityComparer<T>.DefaultMetoda EqualityComparer<T>.Default zwraca ogólny komparator, którego można używać zamiaststatycznej metody object.Equals. Jej zaletą jest to, że najpierw sprawdza, czy typ T implementujeinterfejs IEquatable<T>, i jeśli tak, to wywołuje tamtą implementację, pozwalając uniknąć pakowania.Jest to szczególnie przydatne w metodach generycznych:

Poleć książkęKup książkę

Page 53: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

Dołączanie protokołów równości i porządkowania 331

static bool Foo<T> (T x, T y){ bool same = EqualityComparer<T>.Default.Equals (x, y); ...

IComparer i ComparerKomparatory umożliwiają dołączanie do posortowanych słowników i kolekcji niestandardowej logikiporównawczej.

Dla nieposortowanego słownika, np. Dictionary i Hashtable, komparator jest bezużyteczny — w ta-kim przypadku potrzebny jest IEqualityComparer, aby możliwe było obliczanie wartości skrótów.Analogicznie komparator równości jest nieprzydatny dla posortowanych słowników i kolekcji.

Oto definicje interfejsu IComparer:public interface IComparer{ int Compare(object x, object y);}public interface IComparer <in T>{ int Compare(T x, T y);}

Tak jak w przypadku komparatorów równości, istnieje klasa abstrakcyjna, którą można rozszerzyćzamiast pisać implementację interfejsów:

public abstract class Comparer<T> : IComparer, IComparer<T>{ public static Comparer<T> Default { get; }

public abstract int Compare (T x, T y); // do implementacji przez programist int IComparer.Compare (object x, object y); // do implementacji przez programist}

Poniżej znajduje się przykład ilustrujący klasę opisującą życzenia i komparator sortujący życzenia wgważności:

class Wish{ public string Name; public int Priority;

public Wish (string name, int priority) { Name = name; Priority = priority; }}

class PriorityComparer : Comparer <Wish>{ public override int Compare (Wish x, Wish y) { if (object.Equals (x, y)) return 0; // test bezpiecze stwa return x.Priority.CompareTo (y.Priority); }}

Poleć książkęKup książkę

Page 54: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

332 Rozdział 7. Kolekcje

Test bezpieczeństwa metody object.Equals gwarantuje nam, że nigdy nie zaprzeczymy metodzieEquals. Wywołanie statycznej metody object.Equals jest w tym przypadku lepszym rozwiązaniemniż wywołanie x.Equals, ponieważ metoda ta zadziała także, gdy x będzie null!

Poniżej przedstawiamy przykład użycia naszego komparatora PriorityComparer do posortowanialisty:

var wishList = new List<Wish>();wishList.Add (new Wish ("Pokój", 2));wishList.Add (new Wish ("Bogactwo", 3));wishList.Add (new Wish ("Mi o ", 2));wishList.Add (new Wish ("3 kolejne yczenia", 1));

wishList.Sort (new PriorityComparer());foreach (Wish w in wishList) Console.Write (w.Name + " | ");

// WYNIK: 3 kolejne yczenia | Bogactwo | Mi o | Pokój |

W następnym przykładzie klasa SurnameComparer pozwala na posortowanie nazwisk w kolejnościodpowiedniej dla książki telefonicznej:

class SurnameComparer : Comparer <string>{ string Normalize (string s) { s = s.Trim().ToUpper(); if (s.StartsWith ("MC")) s = "MAC" + s.Substring (2); return s; }

public override int Compare (string x, string y) => Normalize (x).CompareTo (Normalize (y));}

Oto przykład użycia tego komparatora w posortowanym słowniku:var dic = new SortedDictionary<string,string> (new SurnameComparer());dic.Add ("MacPhail", "drugi!");dic.Add ("MacWilliam", "trzeci!");dic.Add ("McDonald", "pierwszy!");

foreach (string s in dic.Values) Console.Write (s + " "); // pierwszy! drugi! trzeci!

Klasa StringComparerStringComparer to gotowa klasa do sprawdzania równości i porównywania łańcuchów, która dodat-kowo umożliwia określenie języka i podjęcie decyzji, czy ma być rozpoznawana wielkość liter.Klasa ta implementuje interfejsy IEqualityComparer i IComparer (oraz ich generyczne wersje), więcmożna jej używać z każdym typem słownika lub posortowanej kolekcji:

// CultureInfo znajduje si w przestrzeni nazw System.Globalization

public abstract class StringComparer : IComparer, IComparer <string>, IEqualityComparer, IEqualityComparer <string>{

Poleć książkęKup książkę

Page 55: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

Dołączanie protokołów równości i porządkowania 333

public abstract int Compare (string x, string y); public abstract bool Equals (string x, string y); public abstract int GetHashCode (string obj);

public static StringComparer Create (CultureInfo culture, bool ignoreCase); public static StringComparer CurrentCulture { get; } public static StringComparer CurrentCultureIgnoreCase { get; } public static StringComparer InvariantCulture { get; } public static StringComparer InvariantCultureIgnoreCase { get; } public static StringComparer Ordinal { get; } public static StringComparer OrdinalIgnoreCase { get; }}

Klasa StringComparer jest abstrakcyjna, więc egzemplarze otrzymuje się przez metody statyczne i wła-sności. Metoda StringComparer.Ordinal odzwierciedla domyślny sposób sprawdzania równości łań-cuchów, a metoda StringComparer.CurrentCulture dotyczy porównywania pod względem kolejności.

W poniższym przykładzie tworzymy porządkowy słownik nierozróżniający wielkości liter, taki żedict["Jan"] i dict["JAN"] znaczą to samo:

var dict = new Dictionary<string, int> (StringComparer.OrdinalIgnoreCase);

W następnym przykładzie sortujemy tablicę imion wg zasad australijskiej odmiany angielskiego:string[] names = { "Tom", "HARRY", "sheila" };CultureInfo ci = new CultureInfo ("en-AU");Array.Sort<string> (names, StringComparer.Create (ci, false));

Ostatni przykład to rozpoznająca kultury wersja komparatora SurnameComparer, który napisaliśmyw poprzedniej sekcji (do porównywania nazwisk w sposób odpowiedni dla książki telefonicznej):

class SurnameComparer : Comparer <string>{ StringComparer strCmp; public SurnameComparer (CultureInfo ci) { // utworzenie rozpoznaj cego wielko liter i kultury komparatora a cuchów strCmp = StringComparer.Create (ci, false); } string Normalize (string s) { s = s.Trim(); if (s.ToUpper().StartsWith ("MC")) s = "MAC" + s.Substring (2); return s; }

public override int Compare (string x, string y) { // bezpo rednie wywo anie metody Compare na naszym komparatorze StringComparer return strCmp.Compare (Normalize (x), Normalize (y)); }}

Interfejsy IStructuralEquatable i IStructuralComparableJak napisaliśmy w poprzednim rozdziale, struktury domyślnie implementują porównywanie struktu-ralne, które polega na tym, że dwie struktury zostają uznane za równe, jeśli wszystkie ich pola sąsobie równe. Czasami jednak strukturalne porównywanie i równość są przydatne także w innych

Poleć książkęKup książkę

Page 56: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

334 Rozdział 7. Kolekcje

typach, np. tablicach i krotkach, do których można je dodać jako protokoły dołączane. W wersji 4.0platformy wprowadzono więc dwa nowe interfejsy:

public interface IStructuralEquatable{ bool Equals (object other, IEqualityComparer comparer); int GetHashCode (IEqualityComparer comparer);}

public interface IStructuralComparable{ int CompareTo (object other, IComparer comparer);}

Przekazywane komparatory IEqualityComparer i IComparer są stosowane do każdego elementuw obiekcie złożonym. Możemy to zademonstrować przy użyciu tablic i krotek, które implementująte interfejsy. W poniższym przykładzie sprawdzamy, czy dwie tablice są sobie równe, najpierw za po-mocą domyślnej metody Equals, a następnie przy użyciu jej wersji z interfejsu IStructuralEquatable:

int[] a1 = { 1, 2, 3 };int[] a2 = { 1, 2, 3 };IStructuralEquatable se1 = a1;Console.Write (a1.Equals (a2)); // fa szConsole.Write (se1.Equals (a2, EqualityComparer<int>.Default)); // prawda

Oto kolejny przykład:string[] a1 = "gdyby kózka nie skaka a".Split();string[] a2 = "GDYBY KÓZKA NIE SKAKA A".Split();IStructuralEquatable se1 = a1;bool isTrue = se1.Equals (a2, StringComparer.InvariantCultureIgnoreCase);

Krotki działają tak samo:var t1 = Tuple.Create (1, "foo");var t2 = Tuple.Create (1, "FOO");IStructuralEquatable se1 = t1;bool isTrue = se1.Equals (t2, StringComparer.InvariantCultureIgnoreCase);IStructuralComparable sc1 = t1;int zero = sc1.CompareTo (t2, StringComparer.InvariantCultureIgnoreCase);

Różnica, jeśli chodzi o krotki, jest taka, że ich domyślne implementacje operacji sprawdzania równościi porównywania mają charakter strukturalny:

var t1 = Tuple.Create (1, "FOO");var t2 = Tuple.Create (1, "FOO");Console.WriteLine (t1.Equals (t2)); // prawda

Poleć książkęKup książkę

Page 57: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

1041

Skorowidz

.ASMX Web Services, 217

.NET Framework, 205

Aabstrakcyjne

klasy, 105składowe, 105

ACL, Access Control List, 861adapter

StringReader, 632StringWriter, 632strumienia, 626

adapterybinarne, 626, 632tekstowe, 626, 627XML, 627

adnotacje, 458ADO.NET, 214adres

IPv4, 664IPv6, 664SMTP, 691URI, 665

agregacje bez ziarna, 428akcesory widoku, 652aksjomaty metody object.Equals,

279aktualizowanie danych, 446aktywacja typów, 774algorytm

MD5, 866porównywania kulturowego,

225porównywania

porządkowego, 225

SHA, 866SHA256, 866SHA384, 866

algorytmy szyfrowania, 874alias extern, 83aliasy typów, 83alternatywy, 1011analiza

działających procesów, 539poleceń, 1018wątków w procesie, 539wyrażeń, 1018

anonimowe wywoływanieskładowych, 790, 831

anulowanie zadań, 942anulowanie zapytania PLINQ,

927API EF, 381API COM, 987API L2S, 381aplikacje

typu WPF, 564Windows Store, 775

APM, AsynchronousProgramming Model, 606

architekturadomeny aplikacji, 959Roslyn, 1014sieci, 661strumienia, 611

archiwum ZIP, 636argument, 28

NumberStyles, 253argumenty

metody GroupJoin, 406metody Join, 406

nazwane, 24, 64, 987typów, 126

ASCII, 229asercja, 515, 522, 529, 858

o zerowej długości, 999, 1010asocjacje, 375ASP.NET, 212ASP.NET 5, 19asynchroniczne wyrażenia

lambda, 593asynchroniczność, 209, 551, 577,

594atak słownikowy, 866atomowość, 882atrapy, 673atrybut, 191, 210, 793

[ComVisible(false)], 991[Conditional], 513, 514[ContractVerification], 537[DataMember], 706[NonSerialized], 720, 722[OnDeserialized], 716, 721[OnDeserializing], 716, 721[OnSerialized], 722[OnSerializing], 716, 722[OptionalField], 723[SecurityTransparent], 847,

848[Serializable], 717[SuppressUnmanagedSecurity],

853[SupressMessage], 537[ThreadStatic], 909APTCA, 847AttributeUsage, 795

Poleć książkęKup książkę

Page 58: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

1042 Skorowidz

atrybutFlags, 122LoaderOptimization, 963

atrybutybitmapowe, 794debuggera, 538informacji wywołującego,

193kompresji, 639nazwane, 192niestandardowe, 794podzespołu, 739pozycyjne, 192pseudoniestandardowe, 795serializacji binarnej, 720szyfrowania, 639warunkowe, 198

automatyczna konkatenacjawęzłów XText, 449

automatyczne usuwanienieużytków, 491

awarie, 532

Bbariera, 906bariera wątku wykonawczego,

905bezpieczeństwo, 210, 839

deklaratywne, 843dostępu kodu, 840imperatywne, 843pliku, 640typów, 18, 123wątków, 528, 558, 886–890

bezpieczne metody krytyczne,850

bezpośrednie osadzaniezasobów, 755

białe znaki, 1023biblioteka, 29

PCL, 19PFX, 918

bibliotekiAPTCA, 852DLL, 973natywne, 973WinRT, 21

binarny rewriter, 520, 521BitTorrent, 692blok

catch, 158finally, 158, 161instrukcji, 28, 33kodu, 27try, 158try-catch-finally, 561try-finally, 486

blokady, 881, 886odczytu i zapisu, 893z możliwością uaktualnienia,

895z podwójnym

zatwierdzeniem, 907bloki try-catch-finally, 169blokowanie, 882

bez wykluczania, 878, 892pętlowe, 919wykluczające, 878

błędyparsowania, 255zaokrąglania liczb

rzeczywistych, 49BMP, Basic Multilingual Plane,

231budowanie wyrażeń zapytań, 381buforowanie, 508bufory o stałym rozmiarze, 196

CCAS, code access security, 840CCW, COM-callable wrapper, 991cele

atrybutów, 192delegatów, 142emisji, 816

certyfikat, 749witryny, 872

ciasteczka, Patrz cookiesciąg tekstowy zapytania, 680CLR, 19, 207, 501

implementacjaindeksatorów, 96

implementacjawłasności, 95

COM, Component ObjectModel, 21, 985

COM+, 216cookies, 682cyfrowy certyfikat witryny, 872czas

bieżący, 236działania programu, 18kompilacji, 18letni, 243UTC, 244

czekanie na zadania, 942czystość funkcyjna, 926czyszczenie egzemplarzy

nasłuchujących, 518

Ddane

statyczne, 132uwierzytelniające, 676

data i godzina, 232deasembler, 819debugger, 538

atrybuty, 538punkty kontrolne, 538

debugowanie, 515definicja równości, 277definiowanie

metod generycznych, 814przestrzeni nazw, 455treści, 438typów, 34typów generycznych, 815własnych atrybutów, 796

deklaracje, 450XML, 452

deklarowanieparametrów typów, 128, 135wielu pól naraz, 88

dekoratory strumieni, 612, 626delegat, 18, 139, 382

Action, 143Func, 143MatchEvaluator, 1004

delegatyasynchroniczne, 607multiemisji, 141zgodność, 145

Poleć książkęKup książkę

Page 59: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

Skorowidz 1043

deserializacja, 699deszyfrowanie wiadomości, 872diagnostyka, 209, 511diagnozowanie wycieku pamięci,

506diagram UML, 355DLL, Dynamic Link Libraries,

985DLR, dynamiczny system

wykonawczy języka, 825DNS, Domain Name Service,

663, 690dokumentacja XML, 200dokumenty, 450dołączane komparatory, 281dołączanie debuggera, 538DOM, 433domeny aplikacji, 211, 959

architektura, 959likwidowanie, 961monitorowanie, 965tworzenie, 961używanie, 962

domyślnainicjalizacja elementów, 54wartość generyczna, 129

domyślneprzestrzenie nazw, 456ustawienia przezroczystości,

852dostawca

formatu, 245–247WordyFormatProvider, 250

dostęp do składowychniepublicznych, 788

dostępność symbolu, 1034dostosowanie kolekcji, 714drobiazgi, 1023

niestrukturalne, 1025strukturalne, 1025

drzewoskładni Roslyn, 1015wyrażeń, 25 154, 362, 382,

386wywołań, 579wywołań asynchronicznych,

591X-DOM, 435

dynamiczna kontrola typów, 111dynamiczne

wybieranie przeciążonychskładowych, 828

wywoływanie składowej, 786dynamiczny

odbiorca, 188system wykonawczy języka,

825dyrektywa preprocesora, 198,

1024#else, 512, 1024#if, 511, 1024#if LOGGINGMODE, 514#line, 1024fixed, 981using, 80, 82using static, 80

działaniemodelu transparentności,

849programu, 860wyliczeń, 269zdarzeń, 148

dziedziczenie, 101, 107dzielenie

całkowitoliczbowe, 45danych między domenami,

967łańcuchów, 223na części, 930przy użyciu skrótów, 929tekstu, 1003zakresowe, 930

dziennik zdarzeńmonitorowanie, 543odczyt danych, 543Windows, 542zapis danych, 542

EEAP, Event-based

Asynchronous Pattern, 607efektywność wykorzystania

pamięci, 40egzekwowanie

kontraktów, 534

egzemplarz, 35nasłuchujący, 518referencyjny, 39

elementy, 53formatowania, 224główne, 492, 493opcjonalne, 470podklasy kolekcji, 714, 734puste, 470składowe, 710, 711

eliminowanie pustychelementów, 461

emisja podzespołu, 1031emitowanie

generycznych typów, 814klas, 814konstruktorów, 812metod, 809podzespołów i typów, 805pól, 811składowych typów, 809właściwości, 811

encja, 468Entity Framework, 368enumerator, 166

Ffabryka abstrakcyjna, 948FIFO, first-in, first-out, 312filtr, 377

wyjątków, 23, 161filtrowanie, 391

z indeksowaniem, 392finalizatory, 29, 99, 493

wskrzeszanie, 496wywoływanie metody

Dispose(), 495flagi parsowania, 250, 254forma daty

długa, 238krótka, 238

format XML, 208formater, 702

SOAP, 722XML, 705

formatery binarne, 706

Poleć książkęKup książkę

Page 60: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

1044 Skorowidz

formatowanie, 244daty i godziny, 254, 255wyliczeń, 257złożone, 248

formularz, 681fragmentacja, 501FTP, File Transfer Protocol, 663,

688funkcja, 18

CreateFileMapping, 979GetComplexMessageHeaders,

513funkcje

asynchroniczne, 582, 589klasy FileStream, 621operatorowe, 177wyrażeniowe, 23

GGAC, Global Assembly Cache,

751, 753generator

liczb losowych, 266list z list, 343

generowaniedynamicznego kodu, 799IL, 799jednostek, 375metod instancji, 810zmiennych lokalnych, 802

generycznekolekcje, 314typy delegacyjne, 143

globalizacja, 261globalny bufor zestawów, 22głębokie klonowanie, 439główne moduły współpracujące,

990granica słowa, 1001granice tablic, 57grupowanie, 416

sekwencji, 390według wielu kluczy, 419

Hhermetyzacja, 17hierarchie obiektów, 396

HTTP, Hypertext TransferProtocol, 663

ciąg tekstowy zapytania, 680cookies, 682dane formularza, 681nagłówki, 680tworzenie serwera, 685

IIANA, Internet Assigned

Numbers Authority, 230identyfikatory, 30IIS, Internet Information

Services, 663IL, Intermediate Language, 20,

737implementowanie

indeksatora, 96interfejsów IComparable, 283interfejsów przeliczeniowych,

293obiektów dynamicznych, 833własności w CLR, 95

implikacje przekazywania przezreferencję, 63

indeksatory, 29, 95, 988indeksowanie tablic, 302inferencja typów literałów

liczbowych, 43informacje

o operatorach zapytań, 388o postępie, 600o woluminie, 646o wskaźnikach, 194

inicjalizacjaelementów, 54pól, 88, 108tablic, 56

inicjalizatoryindeksów, 23kolekcji, 167obiektów, 25, 91, 92, 360własności, 23, 94

initialization vector, IV, 868instalacja

certyfikatu, 749typów, 778

instrukcjabreak, 77, 936continue, 78fixed, 195goto, 78if, 73lock, 879return, 78, 168switch, 74, 823throw, 78try, 158using, 162, 486yield break, 169

instrukcjedeklaracji, 71iteracyjne, 75skoku, 77wyboru, 73wyrażeniowe, 72

integracja z debuggerem, 538interakcja między

subskrybentami., 147interfejs, 17, 116

COM, 985Comparer, 331ICollection, 296, 297ICollection<T>, 297IComparable, 281–283IComparer, 331IConvertible, 258ICustomFormatter, 249IDictionary, 316, 318IDictionary<TKey,TValue>,

317IDispatch, 986IDisposable, 292, 485, 489IEnumerable, 290IEnumerable<T>, 291, 292IEnumerator, 290IEnumerator<T>, 291, 295IEqualityComparer, 320, 328IEqualityComparer<T>, 328IEquatable<T>, 276, 280IFormatProvider, 249IList, 296, 298IList<T>, 298IOrderedEnumerable, 415IOrderedQueryable, 415

Poleć książkęKup książkę

Page 61: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

Skorowidz 1045

interfejsIPermission, 841IProducerConsumer

Collection<T>, 952IProgress<T>, 601IQueryable<T>, 362IReadOnlyList<T>, 299ISerializable, 724IStructuralComparable, 333IStructuralEquatable, 273,

333IUnknown, 986IXmlSerializable, 478, 702,

718, 734Progress<T>, 601

interfejsy, 116jawna implementacja, 117konwersja struktury, 120niegeneryczne, 292przeliczeniowe, 293reimplementacja, 118rozszerzanie, 117stosowanie, 120tworzenie, 120wirtualna implementacja

składowych, 118interoperacyjność macierzysta,

211interpolacja łańcuchów, 23, 53IP, Internet Protocol, 663iteratory, 168

komponowanie sekwencji,170

izolacjadomeny, 654podzespołu, 654typów i zestawów, 969

Jjawna implementacja interfejsu,

117jawne określanie typów, 154jednoczesne przetwarzanie

żądań, 551jednolitość typów, 266jednolity system typów, 17jednostka, entity, 369

językpośredni IL, 20XSLT, 483

językidynamiczne, 836zarządzane, 20

JIT, just-in-time, 20

Kkatalog, 648

bazowy aplikacji, 619specjalny, 644

kategoryzacja znaków, 221, 1009klamry, 73klasa, 17, 29, 87

Aes, 868AggregateException, 948, 949AppContext, 287AppDomain, 970Array, 300, 304ArrayList, 308Assembly, 741, 742, 767AssemblyName, 746AutoResetEvent, 897BackgroundWorker, 608Barrier, 905BinaryReader, 632BinaryWriter, 632BitArray, 314BitConverter, 261BlockingCollection, 955BlockingCollection<T>, 954CodeAccessPermission, 840Collection<T>, 323CollectionBase, 325ConcurrentBag<T>, 953Console, 284Contacts, 478Contract, 521Convert, 258CountdownEvent, 901CryptoStream, 868, 869CSharpCompilationOptions,

1030CSharpSyntaxRewriter, 1029CSharpSyntaxWalker, 1022DataContext, 371

DataContractSerializer, 704,709

DataLoadOptions, 377Debug, 515DelegatingHandler, 674Dictionary<TKey,TValue>,

319DictionaryBase, 327Directory, 641DirectoryInfo, 642Dns, 690DynamicMethod, 799DynamicObject, 833, 834Encoding, 230, 631Enumerable, 412Environment, 285Excel.Application, 987ExpandoObject, 836File, 619, 638FileInfo, 642FileIOPermission, 840FileStream, 841FileSystemWatcher, 647HashSet<T>, 314Hashtable, 319HttpClient, 670, 676HttpClientHandler, 675HttpContent, 672HttpListener, 686HttpMessageHandler, 673HybridDictionary, 320IPAddress, 664KeyedCollection<TKey,

TItem>, 325LambdaExpression, 384Lazy<T>, 907LazyInitializer, 908LinkedList<T>, 310List<T>, 308ListDictionary, 320ManualResetEvent, 900Math, 262Mutex, 885NetDataContractSerializer,

704, 709object, 112, 274ObjectContext, 371OpCodes, 820

Poleć książkęKup książkę

Page 62: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

1046 Skorowidz

klasaOrderedDictionary, 320Parallel, 919, 933ParallelLoopState, 936Path, 642PermissionSet, 842PrincipalPermission, 840Process, 286Publisher, 751Queue, 312Queue<T>, 312Random, 265ReaderWriterLockSlim, 893,

895ReadOnlyCollection<T>, 327RSA, 873RSACryptoServiceProvider,

875SemaphoreSlim, 892SerializationInfo, 725SharedMem, 982SmtpClient, 691SortedDictionary<,>, 321SortedList<,>, 321SortedSet<T>, 314Stack, 313Stack<T>, 313StackFrame, 540StackTrace, 540Stopwatch, 549StorageFile podstawowa, 649StorageFolder, 648Stream, 613StreamReader, 629StreamWriter, 629StringBuilder, 228StringComparer, 332Supplier, 478SurnameComparer, 332SymbolInfo, 1034SyntaxNode, 1015SyntaxTree, 1019System.Exception, 164Task, 569TaskCompletionSource, 575,

577TaskFactory, 948TextReader, 627, 630

TextWriter, 627, 630ThreadLocal<T>, 909, 910,

925TimeZone, 240TimeZoneInfo, 240Trace, 515TraceListener, 516Type, 777TypeInfo, 775, 1035WebClient, 667, 681WebRequest, 669WebResponse, 669XDocument, 450, 451XElement, 479, 480XmlConvert, 245, 259XmlReader, 465, 469, 479

odczytywanie elementów,469

przedrostki, 473przestrzenie nazw, 473sprawdzanie poprawności,

481wczytywanie atrybutów,

472wczytywanie węzłów, 467zastosowania, 476

XmlReaderSettings, 466XmlSerializer, 730XmlWriter, 474, 480

przedrostki, 476przestrzenie nazw, 476wpisywanie atrybutów, 475wpisywanie węzłów, 475zastosowania, 476

ZipArchive, 636ZipFile, 637abstrakcyjne, 105atrybutów, 191bazowe, 108dziedziczenie, 101jednostek Entity Framework,

370jednostek LINQ to SQL, 369metod egzemplarza, 637monitorowania, 515po stronie klienta, 667pochodne, 101pomocnicze, 284

statyczne, 36, 98, 637tworzenie, 120

klauzulacatch, 160else, 73from, 344inicjalizacji, 76into, 410iteracyjna, 76select, 396warunkowa, 76

klient, 552P2P, 662

klientybogate, 212ubogie, 212

klonowanie głębokie, 439klucz, 319

prywatny, 871publiczny, 743, 871

kodIL, 737, 799, 819niebezpieczny, 195niezarządzany, 977programu hosta, 856transparentny, 851zarządzany, 20

kodowanieASCII, 229, 630base64, 259Unicode, 229UTF-16, 231, 631UTF-8, 630

kolejka, 312FIFO, 312komunikatów, 565LIFO, 109typu producent-konsument,

954kolejność elementów, 470, 923

składowych, 711XML, 729inicjalizacji pól, 90, 98, 108wykonywania działań, 67

kolekcja, 208, 289, 322, 713blokująca, 954pokoleniowa, 499współbieżna, 951

Poleć książkęKup książkę

Page 63: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

Skorowidz 1047

kombinacje zapytań, 366komentarz, 27, 33

dokumentacyjny, 200komparator, 331, 415

równości, 331, 419kompilacja, 18, 29

warunkowa, 511, 512kompilator

csc.exe, 29JIT, 20, 95Roslyn, 1013

kompilowanie drzew wyrażeń,382

komponentybibliotek PFX, 918COM, 986

komponowanie sekwencji, 170kompozycja podzapytania, 355kompresja

plików, 636strumienia, 634w pamięci, 636

komunikatyodpowiedzi, 672żądania, 672

konfiguracja Release, 535konflikt nazw, 32konkatenacja

łańcuchów, 52węzłów XText, 449

konsola MMC, 544konstrukcja

funkcyjna, 438try-catch, 561try-catch-finally, 561

konstrukcjegrupujące, 1010sygnalizacyjne, 901

konstruktor bezparametrowy,108

konstruktory, 29, 35, 107egzemplarzy, 89niejawne bez parametrów,

90niepubliczne, 91przeciążanie, 90statyczne, 97

kontekst synchronizacji, 566konteksty typizowane, 372kontrakty, 531

danych, 713kodu, 518, 521

binarny rewriter, 521czystość, 522kompilacja, 521warunki początkowe, 523

sprawdzenie statyczne, 536w konfiguracji Release, 535

kontrawariancja, 136, 145Kontrola konta użytkownika,

UAC, 860kontrola typów

dynamiczna, 111statyczna, 111

kontynuacje, 573, 579, 902na jednym przodku, 947warunkowe, 945z wieloma przodkami, 947zapytania, 358, 410

konwersje, 37dynamiczne, 187, 259dziesiętne, 45jawne, 37jawne niestandardowe, 178liczb rzeczywistych, 258liczbowe, 263między typami

całkowitoliczbowymi, 44między typami

zmiennoprzecinkowymi, 44na format base64, 259niejawne, 37niejawne niestandardowe,

178referencji, 102, 146rozpakowania, 422tablic, 307typu logicznego, 49uchwytów oczekiwania, 903wyliczeń, 121, 267

na łańcuch, 268na typy całkowitoliczbowe,

267z liczb całkowitych, 268

znaków, 52

konwertery typów, 245, 260kopiowanie

płytkie, 302, 307tablicy, 302

kotwice, 1000kowariancja, 133, 146krotki, tuples, 269

porównywanie, 270kryptografia, 864kultura niezmienna, 254kultury, 762kwalifikatory aliasów, 84kwantyfikator, 390, 429, 998,

1009*, 998leniwy, 999zachłanny, 999

LLAN, Local Area Network, 663leksykon języka wyrażeń

regularnych, 1008leniwa inicjalizacja, 906liczby, 262

klasa Math, 262klasa Random, 265struktura BigInteger, 264struktura Complex, 264

licznik wydajności, 544odczyt danych, 546tworzenie, 547wyświetlanie, 545zapis danych, 547

LIFO, last in, first out, 109, 313likwidacja

domen aplikacji, 961obiektów szyfrowania, 870uchwytów oczekiwania, 899

LINQ, Language IntegratedQuery, 25, 208, 335

operatory, 387LINQ to SQL, 368LINQ to XML, 433

DOM, 434lista, 297, 308

kontroli dostępu, ACL, 861

Poleć książkęKup książkę

Page 64: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

1048 Skorowidz

literały, 32całkowitoliczbowe, 42reprezentujące liczby

rzeczywiste, 43lokalizacja, 261

Łłańcuch

formatu, 53, 238, 246null, 221

łańcuchowe wywoływanie metod,181

łańcuchydzielenie, 223formatowania daty i godziny,

254, 255formatowania wyliczeń, 257formatowanie, 244klasa StringBuilder, 228kodowanie tekstu, 229łączenie, 223łączenie dekoratorów, 351łączenie operatorów zapytań,

337mechanizmy konwersji, 257metoda string.Format, 224metody statyczne, 221modyfikowanie, 223niestandardowe formatu, 250niestandardowe numeryczne

formatu, 252numeryczne formatu, 250parsowanie, 244pobieranie znaków, 222połączenia z jednostką, 371porównywanie, 225, 393puste, 221przeszukiwanie, 222standardowe formatu, 250tworzenie, 220zapisywanie deklaracji, 452znaków, 51

łączeniedekoratorów, 351łańcuchów, 223operatorów zapytań, 337sekwencji, 389

łącznik zadań, 603, 605łączność operatorów

lewostronna, 67prawostronna, 67

Mmagazyn danych, 611

komputera, 654kontenery, 655lokalny, 654odczyt i zapis, 655odizolowany, 650, 653podlegający roamingowi,

654położenie, 657sprawdzenie dostępności,

658strumieni, 617

makro, 468manifest

aplikacji .NET, 737–740podzespołu, 737, 738

mapowanieplików w pamięci, 650, 651struktury, 981

mechanizmcookies, 682konwersji, 257usuwania nieużytków, 485,

492, 498–502Close, 485Dispose, 485dostrajanie, 503działanie, 498IDisposable, 485wymuszenie działania, 502

metadane, 20składowych, 783

metoda, 18, 28, 88Abort, 911AddUsings(), 1028Aggregate, 427All, 430Any, 430AppendText(), 629Array.ConvertAll, 307Array.Sort, 306

AsEnumerable, 423AsParallel, 922Assert, 842Average, 426BinarySearch, 304Cancel(), 599, 600Cast, 421Clone, 307Close(), 487CodeAccessPermission.

RevertAssert, 859Combine(), 643ComputeHash, 865, 866Concat, 419Connect(), 692ConstrainedCopy, 307Consume, 957Contains, 430ContinueWith, 943Contract.Assert(), 529Contract.Assume(), 530Contract.EndContractBlock(),

526Contract.Ensures(), 527Contract.EnsuresOnThrow,

528Contract.OldValue<T>, 529Contract.Requires(), 523Contract.Requires<TExcepti

on>, 525Contract.Result<T>Contract.ValueAtReturn<T>,

528ConvertTime, 241Count, 425CreateDomain, 859CreateFileQueryWith

Options(), 648CreateText(), 629CreateViewAccessor(), 652DeepClone(), 707, 709DefaultIfEmpty, 425DefineMethodOverride, 811DefineType, 806Delay(), 599Delete(), 638Demand, 841, 842DescendantNodes(), 1020

Poleć książkęKup książkę

Page 65: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

Skorowidz 1049

DisplayPrimeCounts(), 581Dispose(), 486, 490, 495Distinct, 394DoCallBack, 964Empty, 431Enqueue, 956EnsureInitialized, 908EqualityComparer<T>.

Default, 330Equals, 274, 276, 279Except, 420ExceptWith, 315ExecuteAssembly(), 771FindAll, 305FindAssembly(), 771First, 424FirstNode, 441Flatten, 949FlushFinalBlock, 870Foo(), 599, 811FormatOperand, 821GC.ReRegisterForFinalize(),

497get, 95GetAccessControl(), 640GetAsync(), 672GetAwaiter(), 574GetBankFee(), 882GetBytes, 866GetData, 910GetDiagnostics(), 1017GetEnumerator, 294GetEnumerator(), 658GetFileAsync(), 649GetFooValue, 832GetHashCode, 278, 319GetHostAddresses(), 690GetHostEntry(), 690GetKeyForItem, 325GetManifestResource

Names(), 756GetMembers, 780, 781GetObjectData(), 724GetPrimesCount(), 588GetResult(), 574GetType, 111Go(), 592GroupBy, 416

GroupJoin, 406, 409Handle, 950Increment, 881IndexOf, 305IndexOf/LastIndex, 304Interrupt, 911Intersect, 420IsEquivalentTo(), 1017IsMatch(), 994Join, 406Join(), 554Kind(), 1017Last, 424LastIndexOf, 305LastNode, 441Load, 436LoadFile(), 765, 766, 769LoadFrom(), 765, 766, 769,

771LongCount, 425Matches(), 994Max, 426Min, 426Monitor.Enter, 879, 880Monitor.Exit, 879Move(), 638MoveNext, 290Nodes, 441object.Equals, 274, 332Object.Equals, 273object.ReferenceEquals, 275OnCompleted(), 574OpenText(), 629OperationCompleted(), 595OperationStarted(), 595Parallel.For, 934Parallel.ForEach, 934, 935Parallel.Invoke, 933Parse, 245, 436ParseText(), 1018PrintAnswerToLife(), 591Queryable, 423Range, 431ReadElementString, 472ReadString, 472ReadSubtree, 472ReadToDescendant, 472ReadToFollowing, 472

ReadToNextSibling, 472ReadXml, 477ReadXml(), 735Regex.Match(), 994Regex.Replace(), 1003Register(), 600Repeat, 431Replace(), 1026Resume, 912Save, 807SaveChanges, 379Select, 395SelectMany, 399, 402, 403, 404SendAsync(), 672, 674SequenceEqual, 430set, 95SetAccessControll(), 640SetData, 910SetValue, 303SignalAndWait, 904, 905SignHash, 874Single, 424Skip, 393SkipWhile, 394Stop(), 487string.Format, 224SubmitChanges, 379Sum, 426Suspend, 912SymmetricExceptWith, 315Take, 393TakeWhile, 394Task.Delay(), 577Task.Run(), 570Task.WhenAny(), 603ToArray, 422ToDictionary, 422ToList, 422ToLookup, 422ToString, 112, 238, 245, 437ToString(), 1017ToXmlString, 873TryEnter, 880TryGetSwitch, 287TryParse, 245TryTake, 952Union, 419UnionWith, 315

Poleć książkęKup książkę

Page 66: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

1050 Skorowidz

metodaWait(), 570WaitAll, 904, 942WaitAny, 904WhenAll(), 604Where, 391WindowFromPoint, 854WithChangedText(), 1026WriteAttributes(), 613WriteLine(), 629WriteValue, 475WriteXml(), 735metodyabstrakcyjne, 531agregacji, 390agregacyjne, 425anonimowe, 157asynchroniczne w WinRT, 594częściowe, 26, 100definicja, 100implementacja, 100destrukcyjne, 315do kategoryzacji znaków, 221dostępowe, 93, 95dostępowe zdarzenia, 148dostępowe zdarzeń, 152dynamiczne, 801egzemplarzowe, 181egzemplarzy, 142generujące, 430generyczne, 128, 790definiowanie, 814pobieranie, 787wywoływanie, 787instancji, 803, 810inwariantów obiektu, 520,

529, 530klasy Array, 304klasy DynamicObject, 834klasy Expression, 384klasy Math, 263klasy TimeZoneInfo, 241konwersji, 420krytycznebezpieczne, 850pod względem zabezpieczeń,

849ze względu na wydajność, 849

niebezpieczne, 853obiektu AssemblyName, 747OfType, 421przeciążanie, 89, 108przeszukiwania binarnego,

305ReadContentAsXXX, 471ReadXXX, 471rozszerzające, 180

łańcuchowe wywoływanie,181

metody egzemplarzowe,181

rozszerzeń, 25, 339skrótów, 619sortujące, 306statyczne, 142wczytujące, 471wirtualne, 273wtyczek, 140wyrażeniowe, 89

miejsca wywołania, 826MMC, Microsoft Management

Console, 544model

COM, 21kontraktu danych, 701obiektowy Reflection.Emit,

807programowania

asynchronicznego, 606semantyczny, 1030transparentności, 848, 849,

850wykonawczy PLINQ, 921

moduł sprawdzaniapisowni, 924

moduły, 740, 793współpracujące, 990

modyfikatorasync, 583internal, 114out, 62params, 63private, 114protected, 114protected internal, 114public, 114

readonly, 88ref, 61

modyfikatorydostępu, 114zdarzeń, 153

modyfikowaniedrzewa X-DOM, 444łańcuchów, 223węzłów atrybutów, 445węzłów potomnych, 445domen aplikacji, 965dziennika zdarzeń, 543

MSMQ, 216multiemisja, 141MVC, Model-View-Controller, 212

Nnadawca, 147nadpisane metody, 527, 529nadsubskrypcja procesora, 568nakładanie blokad, 558narzędzia

do generowania jednostek,375

Visual Studio, 761narzędzie signtool.exe, 750natywne biblioteki DLL, 973nawigacja, 440

do rodzica, 443na tym samym poziomie, 444po atrybutach, 444

nazwaelementów, 714kontraktu danych, 705pliku, 619podzespołów, 745symbolu, 1036typów generycznych, 776typów osadzonych, 776typów parametrów, 777wskaźników, 777

niebezpieczny kod, 194niegeneryczny słownik, 320niejawne

określanie typów, 65parametry ref, 988typowane zmienne lokalne,

25

Poleć książkęKup książkę

Page 67: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

Skorowidz 1051

niepowodzenie, 515nieskończoność, 48niestandardowe

komparatory równości, 419łańcuchy formatu, 250

numeryczne łańcuchy formatu,250

Oobiekt, 58

AssemblyName, 746CollectionDataContract, 714CredentialCache, 677HttpClient, 680MailMessage, 691MemberInfo, 781szyfrowania, 870typu DateTime, 235typu DateTimeOffset, 236WebClient, 678WebRequest, 678WebResponse, 678

obiektowość, 17obiekty

dynamiczne, 833klasy Encoding, 230, 231niezmienne, 891potomne, 729

obliczanie skrótów, hashing,864–866

obsługałańcuchów i tekstu, 219wyjątków, 561, 678, 805zdarzeń, 587

oczekiwanie, 583na interfejs użytkownika, 585na zadania, 903

odbiorca, 188odczyt

danych licznika wydajności,546

elementów, 469plików .resources, 758

odizolowany magazyn danych,653

odwołaniado bibliotek DLL, 973do obiektu, 708

do składowych, 202do typów, 202wsteczne, 1011

ograniczaniedostępności, 115innego zestawu, 856

ograniczeniadotyczące klasy bazowej, 130dotyczące klasy i struktury,

131dotyczące konstruktora

bezparametrowego, 131dotyczące typu nagiego, 131kolekcja blokująca, 954modyfikatorów dostępu, 116PLINQ, 924typów generycznych, 130

określanie obiektu stanu, 940opakowanie, 327

zapytań, 358opcja Baseline, 537opcje

wyrażeń regularnych, 996,1011

zmiennej statycznej, 512operacje

asynchroniczne, 577na plikach i katalogach, 637synchroniczne, 577wejścia-wyjścia, 209, 648, 844

operator, 33, 65, 68–70&, 174!=, 273|, 174<, 281, 283==, 273, 276>, 283as, 103AsEnumerable, 367AsQueryable, 383is, 104Join, 407mnożenia, 29nameof, 100null, 70, 175OrderBy, 414OrderByDescending, 414ThenBy, 414

ThenByDescending, 414trójargumentowy, 51typeof, 111, 129warunkowy, 51warunkowy null, 23, 70wskaźnika do składowej, 196zapytania, 335

operatoryagregacji, 343arytmetyczne, 45bitowe, 47elementów, 342, 390, 423inkrementacji i

dekrementacji, 45konwersji, 348LINQ, 387porównywania i równości,

49, 173przypisania, 67relacyjne, 174sprawdzania przepełnienia

całkowitoliczbowego, 46warunkowe, 50wyliczeń, 123zbiorów, 390, 419zmieniające kształt, 389

opóźnienie podpisania, 744optymalizacja, 499, 596

PLINQ, 928własnych agregacji, 931z wartościami lokalnymi, 938

osadzanie typówwspółpracujących, 990

ostrzeżenia pragma, 199

Ppakiet NuGet, 1013pakowanie, 110, 120pamięć, 40

lokalna wątku, 909niezarządzana, 981współdzielona, 651, 978

paralelizm strukturalny, 918parametr, 28, 57, 60

lockTaken, 880out, 787ref, 787, 988

Poleć książkęKup książkę

Page 68: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

1052 Skorowidz

parametryatrybutu, 192metod, 786nazwane, 192opcjonalne, 24, 63, 92, 987pozycyjne, 192typów, 126, 128, 132

parsowanie, 244, 255argumentów, 801IL, 819liczb, 258przez dostawcę formatu, 248

pary zastępcze, 231PCL, Portable Class Libraries, 19pewność przypisania, 59pętla

do-while, 76for, 76foreach, 77while, 76

pętlewewnętrzne, 935zewnętrzne, 935

PFX, 917PIA, primary interop assembly,

990piaskownica, 22pieczętowanie funkcji i klas, 106pierwszy program, 27planista

domyślny, 947kontekstu synchronizacji,

947zadań, 947

planowanie zadań, 947platforma

.NET Framework, 19, 205

.NET Core, 19plik, 649

.resources, 757

.resx, 757signtool.exe, 750XSLT, 483

pliki.edmx, 370.pdb, 540.tlb, 991.winmd, 737

metadanych, 22ZIP, 636

plikowe operacjewejścia-wyjścia, 648, 650

PLINQ, 918, 920anulowanie zapytania, 927kolejność elementów, 923ograniczenia, 924optymalizacja, 928wykonywanie równoległe,

922zastosowania, 926

płytkie kopiowanie, 302pobieranie

atrybutów w czasiedziałania, 797

elementów, 441elementów potomnych, 442jednego elementu, 442metadanych składowych,

783metod generycznych, 787typów osadzonych, 774typów tablicowych, 775wartości wyliczenia, 268znaków, 222

poczta elektronicznaotrzymywanie, 695wysyłanie, 691

podklasyobiektów potomnych, 731typu głównego, 730

podmiot zabezpieczeń, 862podnoszenie uprawnień, 846,

862podpisy cyfrowe, 874podpisywanie kodu, 750podstawowa przestrzeń

wielojęzyczna, BMP, 231podstawowe zestawy

międzyoperacyjne, 25podwyrażenia, 1002podzapytania, 353, 397podzespoły, 737, 738

atrybuty, 739emitowanie, 805ładowanie, 793manifest aplikacji, 739

manifest podzespołu, 738moduły, 740, 793nazwa, 745nazwa kwalifikowana, 746opóźnienie podpisania, 744podpisywanie, 742refleksje, 792repozytorium GAC, 753satelickie, 754, 760silne nazwy, 743ustalanie, 763użycie Authenticode, 749w pojedynczym pliku, 769wczytywanie, 762, 764wdrażanie, 768wersja informacyjna, 747współpracujące COM, 986wyszukiwanie, 762zapisywanie, 807

podział tekstu, 1004pola egzemplarzowe, 910pole, 35, 87polecenie, Patrz instrukcjapolimorfizm, 101

jednokierunkowy, 831wielokierunkowy, 831

ponawianie zgłoszenia wyjątku,163

ponowne obliczanie, 348POP, Post Office Protocol, 663POP3, 695poprawa wydajności, 788poprawność pliku XML, 481porównywanie

krotek, 270łańcuchów, 53, 225, 383

kulturowe, 225pod względem kolejności,

227pod względem równości,

226porządkowe, 225, 282

portyTCP, 664UDP, 664

porządkowanie, 413naturalne, 342

pośrednik, 327

Poleć książkęKup książkę

Page 69: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

Skorowidz 1053

potokianonimowe, 622, 624nazwane, 622, 623

poziom zaufania, 846pożyczanie operatorów, 173praca zdalna, Remoting, 968

międzyprocesowa, 968prefiksy adresów URI, 670procesy, 539profil referencyjny, 21programowanie

asynchroniczne, 578, 579, 606dynamiczne, 210, 825funkcyjne, 18równoległe, 211, 551, 917,

920programy

typu klient, 552wielowątkowe, 552

progresywne budowaniezapytań, 356

projekcja, 394do typów konkretnych, 398do X-DOM, 459z indeksowaniem, 396

protokołydołączane, 273porządkowania, 328równości, 273, 328

protokółHTTP, 662, 680MIDI, 978POP3, 695SetLastError, 980TCP, 664, 692, 697UDP, 664

przechwytywaniestanu lokalnego, 584zdarzeń, 647zmiennych, 349, 560zmiennych iteracyjnych, 156zmiennych zewnętrznych, 155

przeciążaniekonstruktorów, 90metod, 89, 108operatorów, 177, 279

false, 179porównywania, 178

równości, 178true, 179

przedrostek, 454, 457przeglądanie słownika, 319przekazywanie

danych, 672danych formularza, 681przez referencję, 61, 89przez wartość, 60, 89nadmierne, 598stanu, 837wyjątku, 595

przeliczalność, 289przeliczanie, 347przełączanie kontekstu, 555przepełnienie

całkowitoliczbowe, 45przerwanie operacji, 598przesłanianie metody, 278, 279przestrzenie nazw w XML, 453przestrzeń nazw, 29, 79

aliasy, 83globalna, 80import, 83kwalifikatory aliasów, 84powtarzanie, 82kontraktu danych, 706System.ComponentModel,

566System.Cryptography, 868System.Diagnostics, 209System.Reflection, 741System.Reflection.Emit, 807System.Runtime.Serialization,

703System.Text, 208System.Text.Regular

Expressions, 993System.Xml, 465właściwości

zaawansowane, 83zakres, 81

przeszukiwaniedrzewa, 1019łańcuchów, 222tablic, 304

przetwarzanie tekstu, 208przewidywanie, 999

negatywne, 1000

pozytywne, 1000wsteczne, 999

przypisywanieatrybutów, 813ról, 863użytkowników, 863wielu atrybutów, 192

przyrostki literałów liczbowych,43

przysłanianie metod, 810pula wątków, 567punkty kontrolne, 538

RRCW, runtime-callable wrappers,

986rdzeń platformy, 207receptury wyrażeń regularnych,

1005refaktoryzacja, 28referencja this, 92refleksje, 210, 773, 780

atrybutów, 798dla podzespołów, 792składowych, 781

reguły asynchroniczności, 577reimplementacja interfejsu, 118rekurencja blokowania, 897Remoting, 217repozytorium GAC, 752, 753reprezentacja typu dynamic, 186responsywny interfejs

użytkownika, 551REST, REpresentational State

Transfer, 663rodzaje

kodowania tekstu, 229serializatorów, 704uprawnień, 840węzłów, 475

role, 862Roslyn

architektura, 1014drzewa składni, 1015kompilacja, 1030model semantyczny, 1030przestrzenie robocze, 1014

Poleć książkęKup książkę

Page 70: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

1054 Skorowidz

rozgałęzianie, 803rozpakowywanie, 110rozpoznawanie, 108rozszerzanie interfejsu, 117rozszerzenie kontraktu danych,

715równoległe wykonywanie zadań,

939równoległość, 592równość, 279

referencyjna, 272, 273refleksyjna, 276strukturalna, 272wartościowa, 272, 273

równoważenie obciążenia, 930równoważność typów, 990rzutowanie, 37, 102, 679

w dół, 103w górę, 102

Ssekcja CDATA, 468sekwencje, 171, 389

dekoracyjne, 350filtrowanie, 389grupowanie, 390lokalne, 335łączenie, 389porządkowanie, 389projekcja, 389specjalne, 51wyjściowe, 335zagnieżdżone, 389

selektywne egzekwowaniekontraktów, 534

semafory, 892semantyka iteratorów, 168serializacja, 210, 437, 699

atrybuty, 720binarna, 701, 718jawna, 703kolekcji, 732kontraktu danych, 701, 703niejawna, 703obiektów potomnych, 730odwołań do obiektów, 708podklas, 707

tworzenie podklas, 726typów generycznych, 722XML, 727za pomocą ISerializable, 724zaczepy, 715

serializatorDataContractSerializer, 704NetDataContractSerializer,

704serializator kontraktu danych,

717serwer

FTP, 688HTTP, 685POP3, 695proxy, 675SMTP, 691

serwerowe środowiskouruchomieniowe, 501

sieć, 209, 661silne nazwy, 742silnik XML, 702silniki serializacji, 700Silverlight, 214sklep Windows Store, 650skład zapytania

interpretowanego, 365składnia, 30

płynna, 337, 346SQL, 346zapytaniowa, 344, 346

składnikiPFX, 919platformy .NET, 864

składoweabstrakcyjne, 105C#, 784CLR, 784egzemplarza, 35funkcyjne, 18interfejsu, 116interfejsu generycznego, 790klasy Assembly, 742klasy object, 112klasy Stream, 613klasy TextReader, 628klasy TextWriter, 628niepubliczne, 788

odziedziczone, 105prywatne, 36statyczne, 35, 889typów generycznych, 785typu, 35

skompilowane typy, 737skrót, 278skrypt, 837słabe odwołania, 507, 508słowa kluczowe, 30

kontekstowe, 32słowa zarezerwowane, 30słowniki, 316

sortowane, 321słowo kluczowe

async, 582async i await, 582await, 583base, 107, 108Component, 759dynamic, 827extern, 83fixed, 984into, 358let, 361new, 106, 803override, 106public, 36ref, 988stackalloc, 196static, 827using, 1027var, 65virtual, 104volatile, 983

SMTP, Simple Mail TransferProtocol, 663, 691

sortowanie, 306, 415spinning, 555sprawdzanie

granic tablic, 57modelu semantycznego,

1032poprawności dokumentu,

481poprawności drzewa X-DOM,

483poprawności schematów, 480

Poleć książkęKup książkę

Page 71: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

Skorowidz 1055

poziomu zaufania, 846przepełnienia, 46równości, 271, 277sposobu kodowania, 230typów, 971dostępnych liczników, 545kontraktu, 536w miejscu wywołania, 535

SSL, 685stała, 33, 96stan

lokalny, 556, 584współdzielony, 556

standardowełańcuchy formatu, 250operatory zapytań, 335

standardowy wzorzec zdarzeń,149

statyczna kontrola typów, 18,111

statyczne sprawdzeniekontraktu, 536

sterta, 58ogromnych obiektów, 500

stos, 57, 313ewaluacji, 800LIFO, 313

stosowanieblokady, 881zasad dostępu kodu, 845

strategiedziedziczenia, 370projekcji, 360

strefy czasowe, 239, 242struktura, 113

BigInteger, 264Complex, 264DateTime, 233, 239, 243DateTimeOffset, 233, 239DOM wyrażenia, 383drzewa, 1019Guid, 271Nullable<T>, 172SyntaxToken, 1015SyntaxTree, 1015SyntaxTrivia, 1016TextSpan, 1022TimeSpan, 232

strukturalna równośćwartościowa, 277

strukturalne zrównoleglanieprzetwarzania danych, 918

strumienie, 209adapter, 626architektura, 611bezpieczeństwo wątków, 617dekoracyjne, 612kompresja, 634limit czasu, 617magazynu danych, 612, 617obsługa odczytu i zapisu,

615opróżnienie, 616wyszukiwanie, 616zamknięcie, 616zamykanie adapterów, 633

strumieniowanie projekcji, 461strumień

BufferedStream, 625FileStream, 618MemoryStream, 621PipeStream, 622XmlReader, 467

subkultury, 762subskrybent, 147surogat, 231sygnalizacja, 878, 897, 898sygnały dwustronne, 899sygnatura metody, 88sygnatury Func, 341symbole, 1032

zadeklarowane, 1034symetria typów

predefiniowanych, 35symulowanie unii C, 977synchronizacja, 594, 878, 880system

CLR, 20plików

CDFS, 640FAT, 640NTFS, 640przechwytywanie

zdarzeń, 647typów COM, 985

szeregowanieIn i Out, 976klas i struktur, 975typów wspólnych, 974

szyfrowanie, 844kluczem publicznym, 871skrótów, 864SSL, 685symetryczne, 867w pamięci, 868wiadomości, 872

Śścisła kontrola typów, 19śledzenie obiektów, 373środowisko

uruchomieniowe CLR, 501wykonawcze systemu

Windows, 21

Ttabela operatorów, 67tablice, 53, 135, 196

bajtów, 231długość, 304indeksowanie, 302konwertowanie, 307kopiowanie, 307liczba wymiarów, 304nieregularne, 55odwracanie kolejności

elementów, 307prostokątne, 55przeglądanie zawartości, 304przeszukiwanie, 304skrótów, hash tables, 278,

319sortowanie, 306tworzenie, 302w pamięci, 301wielowymiarowe, 55zmienianie rozmiarów, 307

TAP, Task-based AsynchronousPattern, 602

TCP, Transmission and ControlProtocol, 663, 692, 697

Poleć książkęKup książkę

Page 72: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

1056 Skorowidz

technikioptymalizacji, 499synchronizacji, 878wielowątkowości, 877

technologia.ASMX Web Services, 217ADO.NET, 214ASP.NET, 212Authenticode, 748COM+, 216EF, 379L2S, 379LINQ, 25, 208, 335MSMQ, 216PLINQ, 918Silverlight, 214WCF, 216WPF, 213XML, 465

technologieinterfejsu użytkownika, 212zapleczowe, 214

tekst, 208testowanie, 262

podzespołów satelickich, 761testy jednostkowe, 673token anulowania, 927tożsamości, 862transformacja drzewa składni,

1026transparentność, 848, 855tryb pliku, 619tworzenie

asercji, 515deasemblera, 819domen aplikacji, 961drobiazgów, 1027drzewa X-DOM, 437egzemplarzy, 35FileStream, 618funkcji asynchronicznych,

589instancji obiektów, 803instancji typów, 778kompilacji, 1030liczników wydajności, 547łańcuchów, 220

łańcuchów strumieniszyfrowania, 869

obiektów typu DateTime, 235obiektów typu

DateTimeOffset, 236pliku .resx, 758podklas typów generycznych,

131podzespołu satelickiego, 760serwera HTTP, 685struktur, 113tablic, 302tokenów, 1027typów, 87uchwytu EventWaitHandle,

902wątku, 552węzłów, 1027własnych fabryk zadań, 948wyrażeń lambda, 340wyrażeń zapytań, 357zadań, 940zapytań złożonych, 356zasobu pack URI, 759zbioru, 315złączeń, 407

typ, 33bool, 174char, 219CultureInfo, 247DateTimeFormatInfo, 247decimal, 48double, 47, 48dynamic, 186, 187float, 47NumberFormatInfo, 247object, 109, 186string, 52, 220TSource, 341var, 187wyliczeniowy

Environment.SpecialFolder,644

RegexOptions, 995UnmanagedType, 974WebExceptionStatus, 678

typizowanie elementów, 341

typyanonimowe, 25, 182, 360argumenty, 126bazowe, 777całkowitoliczbowe

16-bitowe, 478-bitowe, 47

częściowe, 99definiowane przez

programistę, 277delegacyjne, 139, 145dopuszczające wartość null,

171alternatywa, 176konwersje jawne, 172konwersje niejawne, 172mieszanie operatorów, 174operatory null, 175pakowanie wartości, 172rozpakowywanie wartości,

172zastosowania, 175

generyczne, 125, 276, 776,779dane statyczne, 132definiowanie, 815delegacyjne, 143niezwiązane, 129, 780odwołania do samego

siebie, 132ograniczenia, 130podklasy, 131szablony C++, 137zamknięte, 780, 816

izolacji, 653logiczne, 49liczbowe, 42, 827osadzone, 775otwarte, 126parametry, 126, 128platformy .NET Framework,

887predefiniowane, 34proste, 41referencyjne, 37, 39, 41, 54składowych, 782statyczne, 189

Poleć książkęKup książkę

Page 73: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

Skorowidz 1057

systemowe, 207tablicowe, 135, 775wartościowe, 37, 38, 41, 54węzłów, 1017własne, 35wskaźnikowe, 194współpracujące, 990współpracujące COM, 986wyjątków, 164wyrażeń, 384X-DOM, 435zagnieżdżone, 124zamknięte, 126zwrotne, 28, 139

UUAC, User Account Control, 860uchwyt EventWaitHandle, 902uchwyty zdarzeń oczekiwania,

897, 899, 902udostępnianie obiektów, 991UDP, Universal Datagram

Protocol, 663ukończenie synchroniczne, 596ukrywanie

nazw, 81odziedziczonych

składowych, 105UNC, Universal Naming

Convention, 663unia, 978Unicode, 229unifikacja, 109

typów liczbowych, 827unikanie konfliktów nazw, 32uprawnienia, 839

diagnostyczne, 844dla operacji wejścia i wyjścia,

844dostępu kodu, 839dotyczące interfejsu

użytkownika, 844dotyczące szyfrowania, 844dotyczące tożsamości, 845podstawowe, 843sieciowe, 844UIPermission, 854

URI, Uniform ResourceIdentifier, 663

URL, Uniform Resource Locator,663

uruchamianie zadań, 570, 940usługa, 370ustalanie typu, 763ustawianie stopnia

zrównoleglenia, 927ustawienia przezroczystości, 852usuwanie

elementów składowych, 490nieużytków, 485, 498

automatyczne, 491Close, 485Dispose, 485IDisposable, 485

obiektów, 373sekwencji atrybutów, 446sekwencji węzłów, 446

UTF-16, 231uwierzytelnianie, 676

na podstawie formularzy,684

HttpClient, 678nagłówki, 678

uzgadnianie klucza publicznego,872

uzyskanie drzewa składni, 1018używanie

Authenticode, 749biblioteki PFX, 920delegatów, 140delegatu multiemisji, 142DNS, 690FTP, 688klamer, 73klasy XmlWriter, 480kontraktów kodu, 519, 532PLINQ, 926punktów kontrolnych, 538serializatorów, 704strumieni, 613TCP, 692uchwytów zdarzeń

oczekiwania, 897

VVoice over IP, 692

Wwariancja, 134

parametrów, 146typów, 24

warstwy sekwencji dekoratorów,351

wartości, 447domyślne, 59pobieranie, 448specjalne typów liczbowych,

47ustawianie, 447zwrotne, 571

wartośćNaN, 48Null, 40, 171, 238, 712skrótu, hash code, 278

warunkikontraktu

wyjątki, 534końcowe, 527, 529początkowe, 523, 527

wątek, 211, 552, 965bezpieczeństwo, 558blokowanie, 555dołączanie, 554priorytet, 563przekazywanie danych, 559sygnalizowanie, 564usypianie, 554wywłaszczenie, 553

wątkidziałające w tle, 562aktywne, 562interfejsu użytkownika, 566procesów, 539pula, 567w aplikacjach WPF, 564

wątkowanie, 552WCF, Windows Communication

Foundation, 216wczesne ładowanie, 378

w Entity Framework, 379

Poleć książkęKup książkę

Page 74: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

1058 Skorowidz

wczytywanieatrybutów, 472podzespołu, 764węzłów, 467

wdrażanie podzespołów, 768Web API, 217wektor inicjalizujący, IV, 868wersjonowanie, 723, 753weryfikacja Authenticode, 751węzły

atrybutów, 473potomne, 441XML, 467XText, 449z treścią mieszaną, 449

wiązaniedynamiczne, 24, 183, 989językowe, 185niestandardowe, 185statyczne, 184

wielowątkowość, 877Windows Data Protection, 864Windows Forms, 213Windows RT i Xamarin, 214Windows Store, 650Windows Workflow, 215WinRT, 21, 493wirtualizacja, 862wirtualne składowe funkcyjne, 104własne

atrybuty, 796fabryki zadań, 948liczniki wydajności, 548łączniki zadań, 605

własności, 18, 29, 93automatyczne, 26, 94klasy System.Exception, 164obliczane, 94otoczenia, 175tylko do odczytu, 94wyrażeniowe, 94

właściwości adresu URI, 665właściwość

CodeBase, 767IsGenericType, 780IsGenericTypeDefinition,

780Location, 767

MethodHandle, 782Span, 1017SyntaxTree, 1017

WPF, Windows PresentationFoundation, 213

wpisywanieatrybutów, 475węzłów, 475

wskaźnik, 777do kodu niezarządzanego,

197do składowej, 196pusty, 197

wskrzeszenie, 496współbieżność, 209, 551

drobnoziarnista, 579gruboziarnista, 579, 588w TCP, 694

współpraca COM, 985wtyczka, 140wybór

obiektu synchronizacji, 880trybu pliku, 620

wychodzenie z pętli, 936wyciek

blokady, 880pamięci zarządzanej, 503

wydajność, 788, 885, 901wyjątek, 158, 534, 572, 805

AggregateException, 949ContractException, 522, 525FormatException, 245niezaobserwowany, 572NullReferenceException,

274, 461RuntimeBinderException,

186TypeLoadException, 818UnauthorizedAccess

Exception, 861WebException, 678XmlException, 469

wykonywanieleniwe, 348opóźnione, 347, 350, 356, 376równoległe, 922spekulatywne, 552zapytania, 352

wykorzystanie delegatów, 788wyliczenia, 121, 166

atrybut Flags, 122konwersje, 121, 267operatory, 123

wyliczenieBindingFlags, 789DateTimeStyles, 256TaskCreationOptions, 941

wymagania modelutransparentności, 852

wynik obliczeń, 28wyrażenia, 27, 65

dynamiczne, 188inicjalizacji tablicy, 54, 56lambda, 18, 25, 153, 340, 560,

593jawne określanie typów, 154przechwytywanie

zmiennychzewnętrznych, 155

podstawowe, 66przypisania, 66puste, 66regularne, 993

alternatywy, 1011asercje, 999, 1010granica słowa, 1001grupy, 1002kategorie znaków, 1009kompilowane, 995konstrukcje grupujące,

1010konstrukcje różne, 1011kotwice, 1000kwantyfikatory, 1009nazwane grupy, 1003odwołania wsteczne, 1011opcje, 996, 1011receptury, 1005–1008zastąpienia, 1010zbiory znaków, 1009zestawy znaków, 997znaki sterujące, 996, 1008

stałe, 66typy statyczne, 189zapytań, 18, 25, 337, 343, 357,

381

Poleć książkęKup książkę

Page 75: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

Skorowidz 1059

wysyłanie zapytań, 440wyszukiwanie

elementu potomnego, 1021podzespołów, 762symboli, 1036

wyświetlenie podpisuAuthenticode, 751

wywołaniaanonimowe, 831asynchroniczne, 591dynamiczne, 188komponentu COM, 986konstruktorów bazowych,

813metod generycznych, 787metod instancji, 803składowych, 780, 786składowych interfejsu

generycznego, 790zwrotne, 977

wzorceasynchroniczności, 598

oparte na zadaniu, 602oparte na zdarzeniach, 607

przestarzałe, 606wzorzec

metod TryXXX, 165UnsafeXXX, 851wizytator, 828

XX-DOM, 434

automatyczne głębokieklonowanie, 439

definiowanie przestrzeninazw, 455

domyślne przestrzenie nazw,456

klasa XmlReader, 479klasa XmlWriter, 479konstrukcja funkcyjna, 438ładowanie, 436modyfikowanie drzewa, 444nawigacja do rodzica, 443nawigacja na tym samym

poziomie, 444nawigacja po atrybutach, 444

nawigowanie, 440parsowanie, 436przekształcanie drzewa, 462serializacja, 437sprawdzanie poprawności,

483tworzenie drzewa, 437wysyłanie zapytań, 440zapisywanie, 437

XML, 208, 465dokumentacja, 200

XSD, XML Schema Definition,480

XSLT, Extensible StylesheetLanguage Transformations,483

Zzabezpieczenia

dostępu kodu, 843niebezpiecznych metod, 853systemu operacyjnego, 860

zaczepy serializacji, 715zadania, 569

autonomiczne, 572anulowanie, 942długo wykonywane, 571kontynuacje, 943, 945kontynuacje na jednym

przodku, 947kontynuacje warunkowe,

945kontynuacje z wieloma

przodkami, 947planowanie, 947potomne, 941, 945równoległe wykonywanie,

939sposób wykorzystania, 956tworzenie, 940uruchamianie, 570, 940zimne, 956

zadanie Task<TResult>, 944zagnieżdżanie

blokad, 883dyrektywy using, 82

zakleszczenia, 884

zależności cykliczne, 817zamykanie

adapterów, 633egzemplarzy nasłuchujących,

518zapisywanie deklaracji, 452zapytania, 208

EF, 376interpretowane, 362, 364L2S, 376LINQ, 335o składni mieszanej, 347złożone, 356

zarządzaniekluczami, 871pamięcią, 19

zasadydostępu kodu, 845zabezpieczeń, 855

zasoby, 755zasób pack URI, 759zastąpienia, 1010zastępowanie tekstu, 1003zastosowania

biblioteki PFX, 920typów dopuszczających

wartość null, 175klasy XmlReader, 476klasy XmlWriter, 476

zbiory, 314, 419znaków, 1009

zdarzenia, 29, 147, 508metody dostępowe, 152modyfikatory, 153wzorzec standardowy, 149

zdarzenia systemu plików, 647zdarzenie, 18

AssemblyResolve, 764, 769ContractFailed, 533EntryWritten, 543IncludeSubdirectories, 647

zegary, 505, 913jednowątkowe, 915wielowątkowe, 913

zestaw referencyjny, 22zestawy, 210

zaprzyjaźnione, 115znaków, 997

Poleć książkęKup książkę

Page 76: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie:

1060 Skorowidz

zgłaszanie wyjątków, 162zgodność

delegatów, 145parametrów, 145typów, 145typów zwrotnych, 146

złączenia, 397, 406krzyżowe, 407nierównościowe, 407płaskie zewnętrzne, 411w składni płynnej, 409według wielu kluczy, 409wewnętrzne, 407z widokami wyszukiwania,

411zewnętrzne, 404zewnętrzne lewe, 407

złożonełańcuchy formatu, 224operatory przypisania, 66

zmienianiedefinicji równości, 277nazwy symbolu, 1036ścieżki wykonywania, 73

zmienne, 33, 57iteracyjne, 156lokalne, 28, 65, 72, 557, 802zakresowe, 344, 345, 358, 401zewnętrzne, 155

znacznikidokumentacyjne XML, 201niestandardowe, 202

znakiinterpunkcyjne, 32podwójne, 231sterujące, 996, 1008

znakowanie czasowe, 750zrównoleglanie, 927

przetwarzania danych, 918wykonywania zadań, 918

zużycie pamięci, 492zwalnianie zasobów, 485–488

na żądanie, 489zwrot egzemplarza, 590

Żżądanie uprawnień, 857

Poleć książkęKup książkę

Page 78: Tytuł oryginału: C# 6.0 in a Nutshell, 6th Editionczytelnia.wiedzanaplus.pl/books/276/C_6_0_w_pigulce_Wydanie_VI.pdf · Tytuł oryginału: C# 6.0 in a Nutshell, 6th Edition Tłumaczenie: