Αφαίρεση αντικειμένων στη Visual Basic

Στο άρθρο, "Κωδικοποίηση νέων παρουσιών αντικειμένων", έγραψα για τους διάφορους τρόπους Νέος μπορούν να δημιουργηθούν περιπτώσεις αντικειμένων. Το αντίθετο πρόβλημα, διαθέτοντας ένα αντικείμενο, είναι κάτι που δεν θα πρέπει να ανησυχείτε πολύ συχνά στο VB.NET. Το .NET περιλαμβάνει μια τεχνολογία που ονομάζεται Συλλέκτης σκουπιδιών (GC) που συνήθως φροντίζει τα πάντα πίσω από τις σκηνές σιωπηλά και αποτελεσματικά. Αλλά κατά καιρούς, συνήθως όταν χρησιμοποιείτε ροές αρχείων, αντικείμενα sql ή γραφικά (GDI +) αντικείμενα (δηλαδή, μη διαχειριζόμενους πόρους), ίσως χρειαστεί να ελέγξετε τη διάθεση αντικειμένων στον δικό σας κώδικα.

Πρώτον, Κάποιο Ιστορικό

Ακριβώς όπως μαθαίνω απέξωδιαχειριστής (ο Νέος λέξη-κλειδί) δημιουργεί ένα νέο αντικείμενο, ένα deΟ διαρθρωτής είναι μια μέθοδος που ονομάζεται όταν καταστρέφεται ένα αντικείμενο. Υπάρχει όμως μια παγίδα. Οι άνθρωποι που δημιούργησαν το .NET συνειδητοποίησαν ότι ήταν μια φόρμουλα για σφάλματα αν δύο διαφορετικά κομμάτια του κώδικα θα μπορούσαν πραγματικά να καταστρέψουν ένα αντικείμενο. Επομένως, το .NET GC είναι στην πραγματικότητα σε έλεγχο και είναι συνήθως ο μόνος κώδικας που μπορεί να καταστρέψει την εμφάνιση του αντικειμένου. Το GC καταστρέφει ένα αντικείμενο όταν αποφασίζει και όχι πριν. Κανονικά, αφού ένα αντικείμενο αφήνει πεδίο εφαρμογής, είναι

instagram viewer
κυκλοφόρησε από την κοινή γλώσσα χρόνου εκτέλεσης (CLR). Το GC καταστρέφει όταν το CLR χρειάζεται περισσότερη μνήμη. Έτσι, η κατώτατη γραμμή είναι ότι δεν μπορείτε να προβλέψετε πότε ο GC θα καταστρέψει πραγματικά το αντικείμενο.

(Welllll... Αυτό είναι αλήθεια σχεδόν όλη την ώρα. Μπορείς να καλέσεις GC.Collect και πιέστε a κύκλου συλλογής απορριμμάτων, αλλά οι αρχές λένε γενικά ότι είναι α κακό ιδέα και εντελώς περιττό.)

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

Πελάτης = Τίποτα

Αλλά δεν το κάνει. (Ο ορισμός ενός αντικειμένου σε Τίποτα δεν καλείται συνήθως, dereferencing το αντικείμενο.) Στην πραγματικότητα, σημαίνει απλά ότι η μεταβλητή δεν συνδέεται πια με ένα αντικείμενο. Σε κάποια στιγμή αργότερα, το GC θα παρατηρήσει ότι το αντικείμενο είναι διαθέσιμο για καταστροφή.

Με την ευκαιρία, για τα διαχειριζόμενα αντικείμενα, τίποτα από αυτά δεν είναι πραγματικά απαραίτητο. Αν και ένα αντικείμενο όπως ένα κουμπί θα προσφέρει μια μέθοδο Dispose, δεν είναι απαραίτητο να το χρησιμοποιήσετε και λίγοι άνθρωποι κάνουν. Τα συστατικά Windows Forms, για παράδειγμα, προστίθενται σε ένα αντικείμενο κοντέινερ που ονομάζεται συστατικά. Όταν κλείνετε μια φόρμα, η μέθοδος απόρριψης της γίνεται αυτόματα. Συνήθως, πρέπει μόνο να ανησυχείτε για οποιοδήποτε από αυτά, όταν χρησιμοποιείτε μη διαχειριζόμενα αντικείμενα, και ακόμη και μόνο για να περιγράψετε το πρόγραμμά σας.

Ο συνιστώμενος τρόπος για να απελευθερώσετε τους πόρους που μπορεί να κατέχει ένα αντικείμενο είναι να καλέσετε το Διαθέτω μέθοδος για το αντικείμενο (αν είναι διαθέσιμη) και στη συνέχεια dereference το αντικείμενο.

Πελάτης. Διαθέτω() Πελάτης = Τίποτα

Επειδή το GC θα καταστρέψει ένα ορφανό αντικείμενο, ανεξάρτητα από το αν ορίσατε τη μεταβλητή αντικειμένου σε Τίποτα, δεν είναι πραγματικά απαραίτητο.

Ένας άλλος συνιστώμενος τρόπος για να βεβαιωθείτε ότι τα αντικείμενα καταστρέφονται όταν δεν χρειάζονται πια είναι να βάλετε τον κώδικα που χρησιμοποιεί ένα αντικείμενο σε a Χρησιμοποιώντας ΟΙΚΟΔΟΜΙΚΟ ΤΕΤΡΑΓΩΝΟ. Η χρήση του μπλοκ εγγυάται τη διάθεση ενός ή περισσότερων τέτοιων πόρων όταν τελειώσει ο κωδικός σας μαζί τους.

Στη σειρά GDI +, το Χρησιμοποιώντας το μπλοκ χρησιμοποιείται συχνά για τη διαχείριση αυτών των ενοχλητικών γραφικών αντικειμένων. Για παράδειγμα ...

Χρησιμοποιώντας το MyBrush As LinearGradientBrush _. = Νέα ΓραμμικήΓραμμήΓραμμών Γραμμής (_. Μου. ClientRectangle, _. Χρώμα. Μπλε χρώμα. Το κόκκινο, _. LinearGradientMode. Οριζόντιος) <... ...> Τέλος χρήσης

myBrush διατίθεται αυτόματα όταν εκτελείται το άκρο του μπλοκ.

Η προσέγγιση της GC για τη διαχείριση της μνήμης είναι μια μεγάλη αλλαγή από τον τρόπο που το έκανε το VB6. COM αντικείμενα (που χρησιμοποιούνται από VB6) καταστράφηκαν όταν ένας εσωτερικός μετρητής αναφοράς έφτασε στο μηδέν. Αλλά ήταν πολύ εύκολο να κάνει λάθος, οπότε ο εσωτερικός μετρητής ήταν εκτός λειτουργίας. (Επειδή η μνήμη ήταν δεμένη και δεν ήταν διαθέσιμη σε άλλα αντικείμενα όταν συνέβη αυτό, αυτό ονομάστηκε "διαρροή μνήμης".) Αντ 'αυτού, η GC ελέγχει πραγματικά για να διαπιστώσει αν κάτι αναφέρει ένα αντικείμενο και το καταστρέφει όταν δεν υπάρχουν άλλα βιβλιογραφικές αναφορές. Η προσέγγιση GC έχει μια καλή ιστορία σε γλώσσες όπως η Java και είναι μία από τις μεγάλες βελτιώσεις στο .NET.

Στην επόμενη σελίδα, εξετάζουμε την διασύνδεση IDisposable... τη διεπαφή που πρέπει να χρησιμοποιήσετε όταν χρειάζεται να Απορρίψετε τα μη διαχειριζόμενα αντικείμενα στον δικό σας κώδικα.

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


Κάντε κλικ εδώ για να εμφανίσετε την εικόνα
Κάντε κλικ στο κουμπί Επιστροφή στο πρόγραμμα περιήγησής σας για να επιστρέψετε

Ο κώδικας που προστίθεται μοιάζει με αυτόν (VB.NET 2008):

 Κλάση ResourceClass. Εφαρμογές IDisposable. 'Για την ανίχνευση περιττών κλήσεων. Ιδιωτική διατίθεται ως Boolean = False. 'IDisposable. Προστατευμένα αντικαταστάσιμα υποθέματα (_. ByVal διάθεση ως Boolean) Εάν δεν Me.disposed Στη συνέχεια. Εάν απορρίπτετε Τότε. "Ελεύθερο άλλο κράτος (διαχειριζόμενα αντικείμενα). Τέλος εαν. «Ελευθερώστε τη δική σας κατάσταση (μη διαχειριζόμενα αντικείμενα). Msgstr "Ορισμός μεγάλων πεδίων σε μηδενική τιμή. Τέλος εαν. Me.disposed = Αληθινό. End Sub. #Region "IDisposable Support" 'Αυτός ο κώδικας προστέθηκε από τη Visual Basic σε. 'εφαρμόστε σωστά το μοτίβο μιας χρήσης. Το Public Sub Dispose () υλοποιεί το IDisposable. Διαθέτω. "Μην αλλάξετε αυτόν τον κωδικό. Msgstr "Βάλτε κώδικα καθαρισμού στο. "Απόρριψη (ByVal διαγραφή ως Boolean) παραπάνω. Απόρριψη (True) GC.SuppressFinalize (Me) End Sub. Προστατευμένα αντικαταστήσει Sub Finalize () 'Μην αλλάξετε αυτόν τον κωδικό. Msgstr "Βάλτε κώδικα καθαρισμού στο. "Απόρριψη (ByVal διαγραφή ως Boolean) παραπάνω. Απόρριψη (False) MyBase. Finalize () End Sub. #End Περιοχή. Τέλος κλάσης 

Διαθέτω είναι σχεδόν ένα «επιβαλλόμενο» πρότυπο σχεδίασης προγραμματιστών στο .NET. Υπάρχει πραγματικά μόνο ένας σωστός τρόπος για να το κάνετε και αυτό είναι. Μπορεί να νομίζετε ότι αυτός ο κώδικας κάνει κάτι μαγικό. Δεν το κάνει.

Πρώτα σημειώστε ότι η εσωτερική σημαία διατεθειμένος απλά βραχυκυκλώνετε το όλο θέμα για να μπορείτε να καλέσετε Διάθεση (διάθεση) όσο συχνά θέλετε.

Ο κώδικας ...

 GC.SuppressFinalize (Me) 

... κάνει τον κώδικα πιο αποτελεσματικό, λέγοντας στο GC ότι το αντικείμενο έχει ήδη διατεθεί (μια «δαπανηρή» λειτουργία από πλευράς κύκλων εκτέλεσης). Ο ορισμός είναι Προστατευμένος επειδή το GC το καλεί αυτόματα όταν καταστρέφεται ένα αντικείμενο. Δεν πρέπει ποτέ να καλέσετε τον Finalize. Το Boolean διάθεση αναφέρει τον κώδικα αν ο κώδικας σας ξεκίνησε τη διάθεση του αντικειμένου (True) ή αν το έκανε το GC (ως μέρος του Οριστικοποιώ υπο. Σημειώστε ότι ο μοναδικός κώδικας που χρησιμοποιεί το Boolean διάθεση είναι:

 Εάν απορρίπτετε Τότε. "Ελεύθερο άλλο κράτος (διαχειριζόμενα αντικείμενα). Τέλος εαν 

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

Η ιδέα πίσω από αυτό το απόσπασμα κώδικα είναι ότι προσθέτετε κώδικα για να φροντίζετε τα διαχειριζόμενα και μη διαχειριζόμενα αντικείμενα στις υποδεικνυόμενες τοποθεσίες.

Όταν εξάγετε μια κλάση από ένα βασική κατηγορία που υλοποιεί IDisposable, δεν χρειάζεται να αντικαταστήσετε οποιαδήποτε από τις βασικές μεθόδους αν δεν χρησιμοποιήσετε άλλους πόρους που πρέπει επίσης να διατεθούν. Εάν συμβεί αυτό, η παράγωγη κλάση θα πρέπει να αντικαταστήσει τη μέθοδο Dispose (διάθεση) της κλάσης βάσης για να απορρίψει τους πόρους της παράγωγης κλάσης. Αλλά θυμηθείτε να καλέσετε τη μέθοδο Dispose (διάθεση) της βασικής κλάσης.

Προστατευμένα αντικαταστήσει την Sub Dispose (ByVal διάθεση ως Boolean) Εάν δεν Me.disposed Στη συνέχεια. Εάν απορρίπτετε Τότε. "Προσθέστε τον κωδικό σας στους δωρεάν διαχειριζόμενους πόρους. Τέλος εαν. 'Προσθέστε τον κωδικό σας στους ελεύθερους μη διαχειριζόμενους πόρους. Τέλος εαν. MyBase. Διάθεση (διάθεση) End Sub

Το θέμα μπορεί να είναι ελαφρώς συντριπτικό. Ο σκοπός της εξήγησης εδώ είναι να "απομυθοποιήσει" τι συμβαίνει στην πραγματικότητα επειδή οι περισσότερες πληροφορίες που μπορείτε να βρείτε δεν σας λένε!

instagram story viewer