2011-11-21 9 views
11

Niedawno wykonałem pomiary wydajności na List<> vs [] dla tablicy małych struktur. System.Array wydawał się wygrywać z rękami, więc poszedłem z tym.Czy System.Array wykonuje boks na wartości typów, czy nie?

Dopiero co przyszło mi do głowy, że System.Array zawiera typy obiektów, więc na pewno wypełnienie go strukturami może spowodować boksowanie?

Jednak the MSDN entry for System.Array stany:

W wersji .NET Framework 2.0, klasa Array implementuje System.Collections.Generic.IList<T>, System.Collections.Generic.ICollection<T> i System.Collections.Generic.IEnumerable<T> interfejsy generyczne. Implementacje są dostarczane do tablic w czasie wykonywania, a zatem są niewidoczne dla narzędzi do budowania dokumentacji. W wyniku tego ogólne interfejsy nie pojawiają się w składni deklaracji dla klasy Array i nie ma tematów odniesienia dla elementów interfejsu, które są dostępne pod warunkiem, że są dostępne tylko poprzez rzutowanie tablicy na ogólny interfejs typu (jawne implementacje interfejsu) .

Czy to oznacza, że ​​boks nie występuje mimo wszystko? (I wyjaśniłoby to moje wyniki wydajności)

+0

W celu wyjaśnienia twoich wyników wydajności prawdopodobnie powinniśmy zobaczyć kod użyty do pomiaru wydajności. – Snowbear

Odpowiedz

12

Brak używania tablicy nie jest wyświetlany, jeśli korzystasz z notacji indeksu. np.

new int[2]; 
x=[1]=3; 

gromadzi do następnego IL (nota numery linii są nieistotne, ponieważ pochodzą one z innego fragmentu kodu)

IL_0011: ldc.i4.2 
IL_0012: newarr System.Int32 
IL_0017: stfld Int32[] x 
IL_001c: ldarg.0 
IL_001d: ldfld Int32[] x 
IL_0022: ldc.i4.1 
IL_0023: ldc.i4.3 
IL_0024: stelem.i4 

przypadku języków, które nie mogą korzystać z podziałowe (a ja naprawdę nie wiedzieć, czy istnieją, czy nie) 2 inne metody są tworzone podczas kompilacji dla tablic.

Tworzy tych metod publicznych ::

public int Get(int index) 
public void Set(int index,int value) 

metody te nie box albo i nie są normalnie dostępne za pośrednictwem C#. (Nie pytaj mnie, dlaczego są to metody publiczne). Możesz je wykonać za pomocą IL lub tworząc delegatów do nich. Są wolniejsze, ponieważ jesteś zmuszony zrobić callvirt, aby wywołać te metody.

Rodzina stelem. * I ldelem. * Służy do przechowywania informacji w mocno typowanym typie tablic. Podczas używania generycznych zwykle dołączane są następujące przedrostki: constrained lub readonly podczas korzystania z T[]. Typ stelem.* zwykle nie sprawdza typu. Na przykład. używanie stelem.i4 jest szybsze niż użycie stelem.any Int32, chyba że przedrostek ten zostanie poprzedzony readonly, ponieważ w przeciwnym razie wymusza sprawdzenie typu.

Teraz typecheck jest CAŁKOWICIE bezużyteczny na tablicach wartości znaków, które nie są kowariantne!

Ponieważ środowisko wykonawcze generuje tablicę jednowymiarową zaczynającą się od zera (nazywaną typem SZ_array lub typ wektorowy), są one znane.

Istnieje rodziny IL kodów operacyjnych dla nich: newarr, stelem.*, ldelem.*, ldlen itp

Typ List<T> używa T[] dla swojego sklepu podkładowej Microsoft realizacji plc. List<T> nie boksuje. Bez względu na to, czy używasz listy czy tablicy, przechowujesz rzeczy w tablicy.

+1

Oto dodatkowe łącze do innej odpowiedzi dotyczącej alokacji stosu/stosu tablic i ich zawartych wartości: http://stackoverflow.com/questions/1113892/arrays-heap-and-stack-and-value-types/1114152#1114152 – BoltClock

+1

Ponieważ tablice są typami referencyjnymi, niezapakowane int są również przechowywane w zarządzanej stercie - nie ma w co się pakować. – Alex

Powiązane problemy