Cara terbaik untuk memahami ini adalah dengan melihat bahasa pemrograman tingkat rendah yang dibangun oleh C #.
Dalam bahasa tingkat terendah seperti C, semua variabel masuk satu tempat: Stack. Setiap kali Anda mendeklarasikan variabel, variabel itu berada di Stack. Mereka hanya bisa berupa nilai primitif, seperti bool, byte, int 32-bit, uint 32-bit, dll. Stack sederhana dan cepat. Sebagai variabel ditambahkan mereka hanya pergi satu di atas yang lain, jadi yang pertama Anda mendeklarasikan duduk katakanlah, 0x00, berikutnya pada 0x01, berikutnya pada 0x02 dalam RAM, dll. Selain itu, variabel sering dialamatkan di compile- waktu, sehingga alamat mereka diketahui bahkan sebelum Anda menjalankan program.
Di tingkat berikutnya, seperti C ++, struktur memori kedua yang disebut Heap diperkenalkan. Anda sebagian besar masih tinggal di Stack, tetapi int khusus disebut Pointer dapat ditambahkan ke Stack, yang menyimpan alamat memori untuk byte pertama dari sebuah Object, dan Object tersebut tinggal di Heap. Heap agak berantakan dan agak mahal untuk dipertahankan, karena tidak seperti variabel Stack, mereka tidak menumpuk secara linear ke atas dan kemudian turun ketika program dijalankan. Mereka dapat datang dan pergi tanpa urutan tertentu, dan mereka dapat tumbuh dan menyusut.
Berurusan dengan pointer sulit. Mereka adalah penyebab kebocoran memori, buffer overruns, dan frustrasi. C # untuk menyelamatkan.
Pada level yang lebih tinggi, C #, Anda tidak perlu memikirkan pointer - kerangka .Net (ditulis dalam C ++) memikirkan ini untuk Anda dan menyajikannya kepada Anda sebagai Referensi untuk Objek, dan untuk kinerja, memungkinkan Anda menyimpan nilai yang lebih sederhana seperti bools, bytes, dan ints sebagai Value Type. Di bawah kap, Obyek dan barang-barang yang instantiates Kelas pergi pada Heap, mahal-Managed Heap, sementara Tipe Nilai pergi di tumpukan yang sama yang Anda miliki di C tingkat rendah - super cepat.
Demi menjaga interaksi antara 2 konsep memori yang berbeda (dan strategi penyimpanan) ini secara sederhana dari perspektif pembuat kode, Jenis Nilai dapat Dikemas kapan saja. Boxing menyebabkan nilai yang akan disalin dari Stack, dimasukkan ke dalam Object, dan ditempatkan di Heap - lebih mahal, tetapi, interaksi yang lancar dengan dunia Reference. Seperti jawaban lain tunjukkan, ini akan terjadi ketika Anda misalnya mengatakan:
bool b = false; // Cheap, on Stack
object o = b; // Legal, easy to code, but complex - Boxing!
bool b2 = (bool)o; // Unboxing!
Ilustrasi kuat tentang keuntungan Boxing adalah cek untuk nol:
if (b == null) // Will not compile - bools can't be null
if (o == null) // Will compile and always return false
Objek kami secara teknis adalah alamat di Stack yang menunjuk ke salinan bool b kami, yang telah disalin ke Heap. Kita dapat mengecek o untuk null karena bool telah di-Box dan diletakkan di sana.
Secara umum Anda harus menghindari Boxing kecuali Anda membutuhkannya, misalnya untuk melewatkan int / bool / apa pun sebagai objek argumen. Ada beberapa struktur dasar di. Net yang masih menuntut melewati Jenis Nilai sebagai objek (dan karenanya memerlukan Boxing), tetapi untuk sebagian besar Anda tidak perlu Box.
Daftar struktur C # historis yang tidak lengkap yang membutuhkan Boxing, yang harus Anda hindari:
Sistem Acara ternyata memiliki Kondisi Balap dalam penggunaan naif itu, dan itu tidak mendukung async. Tambahkan masalah Tinju dan mungkin harus dihindari. (Anda bisa menggantinya misalnya dengan sistem acara async yang menggunakan Generics.)
Model Threading dan Timer lama memaksa Box pada parameter mereka tetapi telah digantikan oleh async / wait yang jauh lebih bersih dan lebih efisien.
Koleksi .Net 1.1 sepenuhnya mengandalkan Boxing, karena mereka datang sebelum Generics. Ini masih menendang di System.Collections. Dalam kode baru apa pun Anda harus menggunakan Koleksi dari System.Collections.Generic, yang selain menghindari Tinju juga memberi Anda keamanan jenis yang lebih kuat .
Anda harus menghindari menyatakan atau melewati Jenis Nilai Anda sebagai objek, kecuali jika Anda harus berurusan dengan masalah historis di atas yang memaksa Boxing, dan Anda ingin menghindari hit kinerja Boxing itu nanti ketika Anda tahu itu akan menjadi Boxed pula.
Saran Per Mikael di bawah ini:
Melakukan hal ini
using System.Collections.Generic;
var employeeCount = 5;
var list = new List<int>(10);
Bukan ini
using System.Collections;
Int32 employeeCount = 5;
var list = new ArrayList(10);
Memperbarui
Jawaban ini awalnya menyarankan Int32, Bool dll menyebabkan tinju, padahal sebenarnya itu adalah alias sederhana untuk Jenis Nilai. Artinya, .Net memiliki tipe seperti Bool, Int32, String, dan C # alias untuk bool, int, string, tanpa perbedaan fungsional.