Obiekt (specjalnie użyłem tego określenia) typu int (nie klasy) leży na stosie. A takie obiekty przekazywane są przez wartość.
Tworząc zmienna wprost z typu Object jest ona typem referencyjnym i jego wartość ma być na stercie (na stosie jedynie "wskaźnik");
Mając funkcje (int) przekazywany jest do niej kopia wartości ze stosu...czyli wartość "komórki".
"Podobnie" jest w funkcja przyjmującą type referencyjny... tez jest kopia wartości stosu...tylko akurat to adres :)
Do funkcji jest przekazywany wskaźnik... a dokładnie...kopia wartości wskaźnika.
(i tu i tu jest przekazywanie przez wartość... tylko co innego "wartość" oznacza :)).
W przypadku obiektu wywodzącego się z Value Type ta wartość jest brana bezpośrednio, zaś w innym przypadku, pobrana wartość jest traktowana
jako adres pamięci na stercie.
Dlatego mając funkcje przyjmującą Object, a wywołując ja z "intem" musi przejść przez boxing.
Po prostu funkcja oczekuje adresu a nie konkretnej wartości. Cala tajemnica :)
Aby to zrozumieć fajnie sobie rozrysować na komórki pamieć na stosie i na stercie.
Np:
http://www.csharpstar.com/difference-between-boxing-and-unboxing-in-c/
https://www.codeproject.com/Articles/76153/Six-important-NET-concepts-Stack-heap-value-types
można sobie to rozrysować jeszcze lepiej, tak aby były adresy komórek a nie strzałki.
W większości książek i 95% kursów, temat jest albo omijany aby upraszczany.
Podejrzewam ze wynika to z faktu, że nie autorzy nie chcą tracić "czytelników" nie rozumiejących zagadnień stosu, sterty, wskaźnika, procesu de-referencji.
Niestety (i myślę ze wiele osób sie z tym zgodzi), nie sposób dobrze programować w C# nie czując co jest "pod maska". i jak naprawdę to działa.
P
ps. pisałem na szybko, ale może nigdzie się nie pomylilem