Co oznaczają pojęcia boxing i unboxing? Jeśli ktoś kiedyś przygotowywał się do rozmowy kwalifikacyjnej czy do zaliczenia z podstaw języka C# na studiach, na pewno słyszał/czytał, że powyższe pytanie to pewniak na 100% o to spytają. Może i tak było, ale czy oprócz wykutych regułek orientujecie się, kiedy boxing występuję w praktyce na placu boju. W artykule omówię znane mi przykłady boxingu.

Teoria

Na początek zanim przejdę do praktyki w ramach wyrównanie wiedzy omówię dwa podstawowe terminy powiązane z bieżącym wpisem.

Boxing – jawna/niejawna konwersja typu wartościowego na typ referencyjny

Unboxing jawna konwersja typu referencyjnego na typ wartościowy

Pluginy do VS i R#

Visual Studio jest zazwyczaj codziennym środowiskiem pracy programisty C#. Wykorzystajmy to i wspomóżmy sobie wykrywanie ukrytych alokacji poprzez instalacje jednej z wtyczek:

  • Heap Allocations Viewer (ReSharper)Heap Allocations Viewer
  • Clr Heap Allocation Analyzer (Visual Studio)Clr Heap Allocation Analyzer

Wtyczki analizują kod  w  C#  w  celu znalezienia ukrytych alokacji. Miejsca występowania boxingu prezentowane są podkreśleniem, po najechaniu na zmienną otrzymamy szczegółowy komunikat o wykrytym problemie.

Using plugin

Praktyka (przypadki występowania)

W analizowanych przykładach będę bazował na poniższych strukturach danych.

Boxing występuje w następujących przypadkach:

  • Konwersja typu wartościowego na typ System.Object.
  • Konwersja typu wartościowego na typ System.ValueType.
  • Konwersja typu wyliczeniowego na typ System.Enum.
  • Konwersja typu wartościowego na typ dynamic.
  • Konwersja typu wartościowego na typ interfejsu.
  • Omawiane powyżej przykłady boxingu, występują także w momencie zwracania wartości wyniku z metody, oraz w sytuacji przekazywania argumentu do metody.



    W sytuacji przekazywania implementacji interfejsu IVector, możemy lekko zmodyfikować metodę w celu uniknięcia boxingu (kod poniżej).
  •  Dodawanie elementu do kolekcji typu List<object>.
  •  Dodawanie elementu do nie generycznych kolekcji np. ArrayList, HashTable, SortedList etc.
  • Sprawdzenie czy argument metody nie jest null.
  • Wywołanie nieprzesłoniętych wirtualnych metod na typach wartościowych.

    W powyższym przypadku w celu uniknięcia boxingu wymagana jest implementacja interfejsu IEquatable<T> i przesłonięcie metody ToString().
  • Wywołanie metody klasy bazowej w strukturze.

    W powyższym kodzie został rozwiązany wcześniejszy problem dla wywołanie nieprzesłoniętej metody wirtualnej. Jednak w ciele metody ToString() wywołujemy metodę z klasy bazowej, co powoduje w tym przypadku boxing.
  • Wywołanie metody GetType() na typie wartościowym.
  • Powiązanie zadeklarowanego delegata z metodą typu wartościowego.
  • Konkatenacja stringa z użyciem typu wartościowego.

    W celu zrozumienia wystąpienia boxingu przy konkatenacji stringa podejrzyjmy sobie definicje operatora +. Jako drugi parametr przyjmowany jest wartość typu object.

Podejrzyjmy IL

Jeśli nie lubimy korzystać z pluginów, które podkreślają nam miejsca występowania ukrytej alokacji w Visual Studio możemy zawsze przeanalizować kod IL. Tutaj zaprezentuję dodatkowy przypadek boxingu, którego nie wymieniłem wcześniej w rozdziale Praktyka. W celu kompilacji instrukcji C# do kodu pośredniego IL wykorzystam program LINQPad.

Sample ILW sytuacji użycia dopasowania wzorca (pattern matching) z stałą w instrukcji z is dochodzi do boxingu. Nie będę omawiał po kolei każdej instrukcji IL to, co w tej chwili nas interesuje to wystąpienie instrukcji box (Convert a boxable value to its boxed form) oznaczającej wystąpienie boxingu.

Podsumowanie

Dzisiejszy wpis sięga do postaw, o których klepiąc kolejne klasy typu CRUD zapominamy. Mam nadzieje, że udało mi się  w prosty sposób zaprezentować na przykładach wystąpienie boxingu. Podsumowując boxing i unboxing są kosztownymi konwersjami głównie ze względu na alokacje dodatkowej pamięci podczas boxingu (GC będzie musiał po wszystkim posprzątać).  Jeśli znasz przypadek wystąpienia boxingu, o którym nie wspomniałem to zapraszam do podzielenia się w komentarzu pod tym wpisem.