C# 8.0 wniósł dwie nowości dla tablic jak i wszystkiego co implementuje interfejs IList<T>. Te dwie nowości to Index i Range:
Pierwszą z nowości jest Index - jak sama nazwa wskazuje jest to pozycja elementu w tablicy. Index to typ wartościowy - struktura readonly. Tworzyć obiekt tego typu możemy jak dla każdej innej struktury:
int[] tab = { 1, 2, 3, 4, 5, 6 }; var index0 = new Index(1, fromEnd: true); Console.WriteLine(tab[index0]);
Dodatkowy parametr (opcjonalny) fromEnd pozwala zdefiniować czy szukamy elementu o indeksie 1 od początku kolekcji czy od końca. W tym przypadku otrzymamy 1 wartość od końca czyli 6. Index nie musi być "ręcznie" tworzony w kodzie - możemy posłużyć się operatorem ^ i tak aby pobrać ostatni element wystarczy zapis:
int[] tab = { 1, 2, 3, 4, 5, 6 }; Console.WriteLine(tab[^1]);
Ktoś może zapytać: "zaraz, skoro tablice są numerowane od 0, to dlaczego ostatni element pobieramy za pomocą ^1 a nie ^0"?
Sprawa jest dosyć prosta patrząc na poniższy rysunek, przedstawiający 4 elementową tablicę:
Kiedy chcemy pobrać element kolekcji (np. tablicy) poprzez indeks - żądamy pobrania elementu który zaczyna się na danej pozycji. Czyli dla przykładu jeżeli chcemy pobrać element na pozycji 0 to znaczy że chcemy odczytać wartość zawartą między indeksami 0 i 1. Dlatego własnie, patrząc na rysunek jeżeli chcielibyśmy pobrać wartość elementu ^0 oznaczałoby to chęć pobrania elementu tablicy który jest za ostatnim elementem tablicy, czyli chcemy odczytać pamięć która już nie należy do bloku tablicy. Próba taka zwróci oczywiście błąd. W drugą stronę działa to tak samo - jeżeli chcielibyśmy odczytać element na pozycji 4. Ponieważ tablica ma tylko 4 elementu, nie ma ona wartości dla indeksu między 4 i 5.
Drugą nowością jest operator zakresu. Zakres to nic innego jak dwa indeksy: początek i koniec. Najłatwiej będzie zaprezentować ten operator na przykładach:
static void Main(string[] args) { int[] tab = { 1, 2, 3, 4, 5, 6 }; var range1 = new Range(2, 3); var range2 = 2..3; var range3 = 1..^2; var range4 = Range.All; var range5 = Range.EndAt(2); var range6 = 0..^1; var range7 = ..; var range8 = 2..; var range9 = ..2; PrintContent(tab, range1, nameof(range1)); PrintContent(tab, range2, nameof(range2)); PrintContent(tab, range3, nameof(range3)); PrintContent(tab, range4, nameof(range4)); PrintContent(tab, range5, nameof(range5)); PrintContent(tab, range6, nameof(range6)); PrintContent(tab, range7, nameof(range7)); PrintContent(tab, range8, nameof(range8)); PrintContent(tab, range9, nameof(range9)); } private static void PrintContent(int[] tab, Range range, string rangeName) { Console.WriteLine(rangeName); Console.WriteLine(string.Join(", ", tab[range])); Console.WriteLine(new string('-', 40)); }
- jeżeli nie podamy lewego zakresu (startowego) będzie to zawsze 0
- jeżeli nie podamy prawego zakresu (końcowego) będzie to zawsze -1
- jeżeli stworzymy pusty obiekt zakresu (new Range()) zostanie stworzony zakres 0..0, czyli nie pobierzemy żadnego elementu. Jest to o tyle istotne, że domyślnie dla zakresu ".." dostajemy całą tablicę.
Brak komentarzy:
Prześlij komentarz