Προγραμματισμός

Τα δύο σεντ μου στο Deep copy έναντι ρηχό αντίγραφο στο .Net

Το Microsoft .Net παρέχει υποστήριξη για κλωνοποίηση αντικειμένων - δυνατότητα δημιουργίας ενός ακριβούς αντιγράφου ενός αντικειμένου (γνωστό και ως κλώνος). Η κλωνοποίηση μπορεί να είναι δύο τύπων: ρηχό αντίγραφο και βαθύ αντίγραφο. Ενώ το πρώτο μπορεί να εφαρμοστεί κάνοντας μια κλήση στη μέθοδο MemberwiseClone του Class.Object class, η εφαρμογή της τελευταίας είναι λίγο δύσκολη καθώς δεν έχετε υποστήριξη για αυτό στο πλαίσιο από προεπιλογή. Στην ουσία, ενώ ένα ρηχό αντίγραφο αντιγράφει τις αναφορές χωρίς τα αντικείμενα αναφοράς, ένας βαθύς κλώνος δημιουργεί ένα αντίγραφο του αντικειμένου προέλευσης μαζί με τις αναφορές του.

Ποιες είναι όλες οι διαθέσιμες επιλογές για κλωνοποίηση;

Για να κλωνοποιήσετε μια παρουσία μιας τάξης στο C #, έχετε μερικές επιλογές για να διαλέξετε. Αυτά περιλαμβάνουν τα ακόλουθα:

  • Χρησιμοποιώντας τη μέθοδο System.Object.MemberwiseClone για να εκτελέσετε ένα ρηχό αντίγραφο
  • Χρησιμοποιώντας το Reflection αξιοποιώντας τη μέθοδο Activator.CreateInstance
  • Χρησιμοποιώντας τη σειρά
  • Με την εφαρμογή της διασύνδεσης IClonable

Σημειώστε ότι όταν κλωνοποιείτε αντικείμενα ή παρουσίες τάξεων στο .Net, δεν χρειάζεται να λαμβάνετε υπόψη στατικά μέλη ή στατικά πεδία. Ο λόγος είναι ότι τα στατικά αντικείμενα αποθηκεύονται σε μια κοινόχρηστη θέση μνήμης και διαθέτετε μια θέση μνήμης για αυτά ανά τομέα εφαρμογής.

Ρηχό αντίγραφο έναντι αντιγράφου σε βάθος

Σκεφτείτε μια τάξη Υπάλληλος και ότι δημιουργούμε μια παρουσία της κλάσης Εργαζομένων όπως φαίνεται παρακάτω.

Employee emp = νέος υπάλληλος ();

Υπάλληλος κλώνος = emp;

Ανατρέξτε στο παραπάνω απόσπασμα κώδικα. Ο τελεστής ανάθεσης "=" θα αντιγράψει την αναφορά και όχι το πραγματικό αντικείμενο. Η μέθοδος MemberwiseClone () που ορίζεται στην κλάση System.Object κάνει ακριβώς το ίδιο πράγμα. Αυτά είναι παραδείγματα ρηχών αντιγράφων. Ως εκ τούτου, όταν χρησιμοποιείτε έναν χειριστή ανάθεσης για αντιγραφή και αντιγραφή σε άλλο ή, χρησιμοποιήστε τη μέθοδο Memberwise.Clone (), κάνετε πραγματικά ένα ρηχό αντίγραφο του αντικειμένου.

Ενώ σε ρηχό αντίγραφο τα μέλη του αντιγραμμένου αντικειμένου αναφέρονται στο ίδιο αντικείμενο με το αρχικό αντικείμενο, σε ένα βαθύ αντίγραφο, δημιουργούνται ξεχωριστές εμφανίσεις κάθε μέλους τύπου αναφοράς στην αρχική παρουσία στη νέα ή κλωνοποιημένη παρουσία. Επομένως, εάν έχετε έναν τύπο αναφοράς στην αρχική παρουσία, η νέα παρουσία θα περιέχει επίσης το ίδιο μέλος τύπου αναφοράς σε αυτό, αλλά αυτός ο τύπος αναφοράς θα δείχνει σε μια εντελώς νέα παρουσία.

Σε ρηχό αντίγραφο, δημιουργείται ένα νέο αντικείμενο και στη συνέχεια αντιγράφονται τα μη στατικά μέλη του αντικειμένου προέλευσης στο αντικείμενο προορισμού ή στο νέο αντικείμενο. Εάν το μέλος είναι ένα πεδίο τύπου τιμής, εκτελείται ένα αντίγραφο του πεδίου λίγο προς λίγο. Αντίθετα, εάν το μέλος που αντιγράφεται είναι τύπος αναφοράς, η αναφορά αντιγράφεται. Ως εκ τούτου, το μέλος αναφοράς μέσα στο αρχικό αντικείμενο και τα αντικείμενα στόχου αναφέρονται στο ίδιο αντικείμενο στη μνήμη.

Εάν έχετε μια συλλογή με μεμονωμένα στοιχεία μέσα και θέλετε να εκτελέσετε ένα ρηχό αντίγραφο της παρουσίας συλλογής. Θα πρέπει να σημειωθεί ότι ένα ρηχό αντίγραφο μιας παρουσίας συλλογής αντιγράφει τη δομή της συλλογής αλλά όχι τα στοιχεία μέσα στη συλλογή. Ως εκ τούτου, αφού εκτελέσετε ένα ρηχό αντίγραφο της παρουσίας συλλογής, θα έχετε δύο συλλογές που μοιράζονται τα μεμονωμένα στοιχεία της συλλογής. Αντίθετα, εάν εκτελέσετε ένα βαθύ αντίγραφο της παρουσίας συλλογής, θα έχετε διπλές παρουσίες συλλογής με τα μεμονωμένα στοιχεία της αρχικής συλλογής.

Εφαρμογή αντιγράφου σε βάθος χρησιμοποιώντας σειριοποίηση

Μπορείτε να εφαρμόσετε σε βάθος αντίγραφο με πολλούς τρόπους. Ένας από τους πιο προτιμώμενους τρόπους για την εφαρμογή ενός αντιγράφου σε βάθος ενός αντικειμένου είναι με τη χρήση σειριοποίησης. Μπορείτε επίσης να αξιοποιήσετε τον προβληματισμό για να εκτελέσετε ένα βαθύ αντίγραφο μιας παρουσίας μιας τάξης. Το παρακάτω απόσπασμα κώδικα απεικονίζει πώς μπορείτε να γράψετε μια μέθοδο που εφαρμόζει δυαδική σειριοποίηση για να εκτελέσει ένα βαθύ αντίγραφο μιας παρουσίας χρησιμοποιώντας το C #.

δημόσιο στατικό T DeepCopy (T obj)

       {

εάν (! typeof (T). Είναι Serializable)

           {

ρίξτε νέα εξαίρεση ("Το αντικείμενο προέλευσης πρέπει να είναι σειριοποιήσιμο");

           }

εάν (Object.ReferenceEquals (obj, null))

           {

ρίξτε νέα εξαίρεση ("Το αντικείμενο προέλευσης δεν πρέπει να είναι μηδενικό");

           }

T αποτέλεσμα = προεπιλογή (T);

χρησιμοποιώντας (var memoryStream = νέο MemoryStream ())

           {

var formatter = νέο BinaryFormatter ();

formatter.Serialize (memoryStream, obj);

memoryStream.Seek (0, SeekOrigin.Begin);

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

memoryStream.Close ();

           }

αποτέλεσμα επιστροφής;

       }

Λαμβάνοντας υπόψη ότι έχετε μια κλάση οντοτήτων που ονομάζεται Υπάλληλος, μπορείτε να εκτελέσετε ένα εκτενές αντίγραφο μιας παρουσίας της κλάσης υπαλλήλων, όπως φαίνεται στο απόσπασμα κώδικα παρακάτω.

static void Main (συμβολοσειρά [] args)

       {

Employee emp = νέος υπάλληλος ();

emp.Em EmployeeId = 1;

emp.FirstName = "Joydip";

emp.LastName = "Kanjilal";

Υπάλληλος κλώνος = DeepCopy (emp);

εάν (Object.ReferenceEquals (emp, κλώνος))

           {

Console.WriteLine ("Οι αναφορές είναι ίδιες.");

           }

αλλού

           {

Console.WriteLine ("Οι αναφορές είναι διαφορετικές.");

           }

       }

Όταν εκτελείτε το παραπάνω πρόγραμμα, θα εκτελεστεί ένα βαθύ αντίγραφο της παρουσίας "emp" και το μήνυμα "Οι αναφορές είναι διαφορετικές." θα εμφανιστεί.