Dua sen saya pada salinan dalam vs salinan dangkal di .Net

Microsoft .Net menyediakan dukungan untuk mengkloning objek - kemampuan untuk membuat salinan persis dari suatu objek (juga dikenal sebagai kloning). Kloning dapat terdiri dari dua jenis: salinan dangkal dan salinan dalam. Sementara yang pertama dapat diimplementasikan dengan membuat panggilan ke metode MemberwiseClone dari kelas System.Object, mengimplementasikan yang terakhir agak rumit karena Anda tidak memiliki dukungan untuk itu dalam kerangka kerja secara default. Intinya, sementara salinan dangkal menyalin referensi tanpa objek yang direferensikan, klon yang dalam membuat salinan objek sumber bersama dengan referensinya.

Apa saja opsi yang tersedia untuk kloning?

Untuk mengkloning instance kelas di C #, Anda memiliki beberapa opsi untuk dipilih. Ini termasuk yang berikut:

  • Menggunakan metode System.Object.MemberwiseClone untuk melakukan penyalinan dangkal
  • Menggunakan Refleksi dengan memanfaatkan metode Activator.CreateInstance
  • Menggunakan Serialisasi
  • Dengan mengimplementasikan antarmuka IClonable

Perhatikan bahwa saat menggandakan objek atau instance kelas di .Net, Anda tidak perlu mempertimbangkan anggota statis atau bidang statis. Alasannya adalah bahwa objek statis disimpan di lokasi memori bersama dan Anda memiliki satu lokasi memori yang dialokasikan untuk mereka per domain aplikasi.

Salinan dangkal vs. salinan dalam

Pertimbangkan kelas Karyawan dan kami membuat turunan dari kelas Karyawan seperti yang ditunjukkan di bawah ini.

Employee emp = new Employee();

Employee clone = emp;

Lihat cuplikan kode di atas. Operator penugasan "=" akan menyalin referensi dan bukan objek sebenarnya. Metode MemberwiseClone () yang ditentukan di kelas System.Object melakukan hal yang persis sama. Ini adalah contoh salinan dangkal. Karenanya ketika Anda menggunakan operator penugasan untuk menyalin dan menolak yang lain atau, gunakan metode Memberwise.Clone (), Anda sebenarnya melakukan salinan dangkal objek.

Sementara di salinan dangkal anggota dari objek yang disalin merujuk ke objek yang sama sebagai objek asli, dalam salinan dalam, contoh terpisah dari setiap anggota tipe referensi dalam contoh asli dibuat dalam contoh baru atau kloning. Oleh karena itu, jika Anda memiliki tipe referensi dalam instance asli, instance baru juga akan berisi anggota tipe referensi yang sama di dalamnya, tetapi tipe referensi ini akan mengarah ke instance yang sama sekali baru.

Dalam salinan dangkal, objek baru dibuat dan kemudian anggota non-statis dari objek sumber disalin ke objek target atau objek baru. Jika anggota adalah bidang tipe nilai maka salinan bidang sedikit demi sedikit dilakukan. Sebaliknya, jika anggota yang disalin adalah tipe referensi, referensi tersebut disalin. Karenanya, anggota referensi di dalam objek asli dan objek target merujuk ke objek yang sama di memori.

Jika Anda memiliki koleksi dengan elemen individual di dalamnya dan Anda ingin melakukan salinan dangkal contoh collection. Perlu dicatat bahwa salinan dangkal dari contoh koleksi menyalin struktur koleksi tetapi bukan elemen di dalam koleksi. Karenanya, setelah Anda melakukan salinan dangkal dari contoh koleksi, Anda akan memiliki dua koleksi yang berbagi elemen individu dari koleksi. Sebaliknya, jika Anda melakukan salinan dalam dari contoh koleksi, Anda akan memiliki dua contoh koleksi dengan elemen individu dari koleksi asli digandakan.

Menerapkan salinan dalam menggunakan serialisasi

Anda dapat menerapkan salinan dalam dengan banyak cara. Salah satu cara yang paling disukai untuk mengimplementasikan salinan dalam suatu objek adalah dengan menggunakan serialisasi. Anda juga dapat memanfaatkan refleksi untuk melakukan salinan mendalam dari sebuah instance kelas. Cuplikan kode berikut mengilustrasikan bagaimana Anda dapat menulis metode yang mengimplementasikan serialisasi biner untuk melakukan salinan dalam dari sebuah instance menggunakan C #.

public static T DeepCopy(T obj)

       {

           if (!typeof(T).IsSerializable)

           {

               throw new Exception("The source object must be serializable");

           }

           if (Object.ReferenceEquals(obj, null))

           {

               throw new Exception("The source object must not be null");

           }

           T result = default(T);

           using (var memoryStream = new MemoryStream())

           {

                var formatter = new BinaryFormatter();

               formatter.Serialize(memoryStream, obj);

               memoryStream.Seek(0, SeekOrigin.Begin);

               result = (T)formatter.Deserialize(memoryStream);

               memoryStream.Close();

           }

           return result;

       }

Mengingat Anda memiliki kelas entitas yang disebut Karyawan, Anda dapat melakukan salinan dalam dari sebuah instance kelas Karyawan seperti yang ditunjukkan pada cuplikan kode di bawah ini.

static void Main(string[] args)

       {

           Employee emp = new Employee();

           emp.EmployeeId = 1;

           emp.FirstName = "Joydip";

           emp.LastName = "Kanjilal";

           Employee clone = DeepCopy(emp);

           if(Object.ReferenceEquals(emp, clone))

           {

               Console.WriteLine("References are the same.");

           }

           else

           {

               Console.WriteLine("References are different.");

           }

       }

Saat Anda menjalankan program di atas, salinan dalam dari contoh "emp" akan dijalankan dan pesan "Referensi berbeda." akan ditampilkan.