Dua sen saya pada Salinan dalam vs Salinan cetek di. Bersih

Microsoft .Net memberikan sokongan untuk mengklon objek - kemampuan untuk membuat salinan objek yang tepat (juga dikenal sebagai klon). Pengklonan boleh terdiri daripada dua jenis: salinan cetek dan salinan dalam. Walaupun yang pertama dapat dilaksanakan dengan membuat panggilan ke kaedah MemberwiseClone dari sistem System.Object, melaksanakan yang terakhir agak rumit kerana anda tidak mempunyai sokongan untuk itu dalam kerangka secara lalai. Pada dasarnya, sementara salinan cetek menyalin rujukan tanpa objek yang dirujuk, klon dalam membuat salinan objek sumber berserta rujukannya.

Apakah semua pilihan yang ada untuk pengklonan?

Untuk mengklon contoh kelas di C #, anda mempunyai beberapa pilihan untuk dipilih. Ini termasuk yang berikut:

  • Menggunakan kaedah System.Object.MemberwiseClone untuk melakukan salinan cetek
  • Menggunakan Refleksi dengan memanfaatkan kaedah Activator.CreateInstance
  • Menggunakan Serialisasi
  • Dengan melaksanakan antara muka IClonable

Perhatikan bahawa semasa mengklon objek atau contoh kelas di. Net, anda tidak perlu mempertimbangkan ahli statik atau medan statik. Sebabnya ialah objek statik disimpan di lokasi memori bersama dan anda mempunyai satu lokasi memori yang diperuntukkan untuknya setiap domain aplikasi.

Salinan cetek berbanding salinan dalam

Pertimbangkan kelas Karyawan dan kami membuat contoh kelas Karyawan seperti yang ditunjukkan di bawah.

Employee emp = new Employee();

Employee clone = emp;

Rujuk coretan kod di atas. Operator tugas "=" akan menyalin rujukan dan bukan objek sebenar. Kaedah MemberwiseClone () yang ditentukan dalam kelas System.Object melakukan perkara yang sama. Ini adalah contoh salinan cetek. Oleh itu, apabila anda menggunakan pengendali tugasan untuk menyalin dan membantah yang lain atau, menggunakan kaedah Memberwise.Clone (), anda sebenarnya melakukan salinan objek yang cetek.

Semasa dalam salinan cetek anggota objek yang disalin merujuk pada objek yang sama dengan objek asal, dalam salinan dalam, contoh terpisah dari setiap anggota jenis rujukan dalam contoh asal dibuat dalam contoh baru atau kloning. Oleh itu, jika anda mempunyai jenis rujukan dalam contoh asal, contoh baru juga akan mengandungi anggota jenis rujukan yang sama di dalamnya tetapi jenis rujukan ini akan menunjukkan contoh yang sama sekali baru.

Dalam salinan cetek, objek baru dibuat dan kemudian anggota objek sumber yang tidak statik disalin ke objek sasaran atau objek baru. Sekiranya ahli adalah bidang jenis nilai maka salinan medan sedikit demi sedikit dilakukan. Sebaliknya, jika anggota yang disalin adalah jenis rujukan, rujukan itu disalin. Oleh itu, anggota rujukan di dalam objek asal dan objek sasaran merujuk kepada objek yang sama dalam memori.

Sekiranya anda mempunyai koleksi dengan elemen individu di dalamnya dan anda ingin melakukan salinan cetek contoh koleksi. Harus diingat bahawa salinan cetek contoh koleksi menyalin struktur koleksi tetapi bukan unsur-unsur di dalam koleksi. Oleh itu, setelah anda membuat salinan cetek contoh koleksi, anda akan mempunyai dua koleksi yang berkongsi unsur-unsur koleksi masing-masing. Sebaliknya, jika anda melakukan salinan mendalam dari contoh koleksi, anda akan mempunyai dua contoh koleksi dengan elemen individu koleksi asal diduplikasi.

Melaksanakan salinan mendalam menggunakan siri

Anda boleh melaksanakan salinan dalam dengan banyak cara. Salah satu cara yang paling disukai untuk melaksanakan salinan mendalam objek adalah dengan menggunakan serialisasi. Anda juga dapat memanfaatkan refleksi untuk melakukan salinan mendalam dari contoh kelas. Coretan kod berikut menggambarkan bagaimana anda boleh menulis kaedah yang menerapkan siriisasi binari untuk melakukan salinan mendalam dari contoh 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;

       }

Memandangkan anda mempunyai kelas entiti yang disebut Karyawan, anda dapat melakukan salinan mendalam dari contoh kelas Karyawan seperti yang ditunjukkan dalam potongan kode di bawah.

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.");

           }

       }

Ketika anda menjalankan program di atas, salinan mendalam dari contoh "emp" akan dilakukan dan pesan "Rujukan berbeda." akan dipaparkan.