Właśnie natknąłem się na ten ArraySegment<byte>
typ podczas tworzenia podklasy MessageEncoder
.
Teraz rozumiem, że jest to segment danej tablicy, przyjmuje przesunięcie, nie jest wyliczalny i nie ma indeksatora, ale nadal nie rozumiem jego użycia. Czy ktoś mógłby wyjaśnić na przykładzie?
ArraySegment
jest wyliczalny w .Net 4.5.Odpowiedzi:
ArraySegment<T>
stało się dużo bardziej przydatne w .NET 4.5 + i .NET Core, ponieważ teraz implementuje:IList<T>
ICollection<T>
IEnumerable<T>
IEnumerable
IReadOnlyList<T>
IReadOnlyCollection<T>
w przeciwieństwie do wersji .NET 4, która nie implementowała żadnych interfejsów.
Klasa może teraz uczestniczyć w cudownym świecie LINQ, dzięki czemu możemy wykonywać zwykłe czynności LINQ, takie jak przeszukiwanie zawartości, odwracanie zawartości bez wpływu na oryginalną tablicę, pobranie pierwszego elementu i tak dalej:
źródło
GetEnumerator
prywatne, co oznacza, że musisz rzucić naIEnumerable<T>
(konwersję bokserską), aby to nazwać. Fuj!W tym przykładzie przyjrzymy się, jak można użyć oryginalnej tablicy, właściwości Offset i Count, a także jak można przechodzić przez elementy określone w ArraySegment.
ArraySegment Structure - o czym myśleli?
źródło
i < segment.Offset + segment.Count
.Jest to słaba struktura małego żołnierza, która nic nie robi, ale utrzymuje odniesienie do tablicy i przechowuje zakres indeksu. Trochę niebezpieczne, uważaj, że nie tworzy kopii danych tablicy iw żaden sposób nie czyni tablicy niezmienną ani nie wyraża potrzeby niezmienności. Bardziej typowym wzorcem programowania jest po prostu zachowanie lub przekazanie tablicy i zmiennej lub parametru długości, tak jak ma to miejsce w metodach .NET BeginRead (), String.SubString (), Encoding.GetString () itp.
Nie ma większego zastosowania w .NET Framework, z wyjątkiem tego, co wydaje się być jednym konkretnym programistą firmy Microsoft, który pracował na gniazdach internetowych i lubił go WCF. Co jest prawdopodobnie właściwą wskazówką, jeśli ci się spodoba, użyj jej. Zrobił peek-a-boo w .NET 4.6, dodana metoda MemoryStream.TryGetBuffer () używa go.
out
Zakładam, że wolę mieć dwa argumenty.Ogólnie rzecz biorąc, bardziej uniwersalne pojęcie plasterków jest wysoko na liście życzeń głównych inżynierów .NET, takich jak Mads Torgersen i Stephen Toub. Ten ostatni uruchomił
array[:]
propozycję składni jakiś czas temu, możesz zobaczyć, o czym myśleli na tej stronie Roslyn . Zakładam, że to ostatecznie zależy od uzyskania obsługi CLR. Jest to aktywnie rozważane w przypadku języka C # w wersji 7 afaik, miej oko na System.Slices .Aktualizacja: martwy link, ten dostarczany w wersji 7.2 jako Span .
Update2: większa obsługa w języku C # w wersji 8.0 z typami Range i Index oraz metodą Slice ().
źródło
A co z klasą opakowującą? Tylko po to, aby uniknąć kopiowania danych do buforów czasowych.
Przykład:
Ouput:
źródło
IEnumerable<T>
a następnie dodać IEnumeratorIEnumerable.GetEnumerator() { return GetEnumerator(); }
ArraySegment jest ZNACZNIE bardziej przydatny, niż mogłoby się wydawać. Spróbuj przeprowadzić następujący test jednostkowy i przygotuj się na zaskoczenie!
Widzisz, wszystko, co musisz zrobić, to rzucić ArraySegment na IList, a on wykona wszystkie rzeczy, których prawdopodobnie oczekiwałeś. Zwróć uwagę, że typem nadal jest ArraySegment, mimo że zachowuje się jak zwykła lista.
WYNIK:
źródło
IList<T>
. Spodziewałbym się, że indeksator będziepublic
.W prostych słowach: zachowuje odniesienie do tablicy, pozwalając na wiele odniesień do jednej zmiennej tablicowej, z których każde ma inny zakres.
W rzeczywistości pomaga to używać i przekazywać sekcje tablicy w bardziej ustrukturyzowany sposób, zamiast posiadania wielu zmiennych, do przechowywania indeksu początkowego i długości. Zapewnia również interfejsy kolekcji, które ułatwiają pracę z sekcjami tablic.
Na przykład poniższe dwa przykłady kodu robią to samo, jeden z ArraySegment, a drugi bez:
i,
Oczywiście pierwszy fragment kodu jest bardziej preferowany, szczególnie gdy chcesz przekazać do funkcji segmenty tablicy.
źródło