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

Βέλτιστες πρακτικές στη χρήση Διαθέστε και ολοκληρώστε το .Net

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

Το GC χρησιμοποιεί γενιές για να διατηρεί και να διαχειρίζεται τη σχετική διάρκεια ζωής των αντικειμένων που δημιουργούνται στη μνήμη. Τα αντικείμενα που δημιουργούνται νέα τοποθετούνται στη γενιά 0. Η βασική παραδοχή είναι ότι ένα νέο αντικείμενο μπορεί να έχει μικρότερο χρόνο ζωής, ενώ ένα αντικείμενο που είναι παλιό, μπορεί να έχει μεγαλύτερο χρόνο ζωής. Όταν τα αντικείμενα που κατοικούν στη γενιά 0 δεν ανακτώνται μετά από έναν κύκλο GC, μετακινούνται στη γενιά 1. Ομοίως, εάν αντικείμενα που κατοικούν στη γενιά 1 επιβιώσουν από μια εκκαθάριση GC, μετακινούνται στη γενιά 2. Σημειώστε ότι το GC εκτελείται πιο συχνά στο χαμηλότερες γενιές που στις υψηλότερες. Έτσι, τα αντικείμενα που βρίσκονται στη γενιά 0 θα καθαρίζονται συχνότερα σε σύγκριση με τα αντικείμενα που βρίσκονται στη γενιά 1. Επομένως, είναι μια καλύτερη πρακτική προγραμματισμού να διασφαλίζετε ότι χρησιμοποιείτε περισσότερα τοπικά αντικείμενα που αντικείμενα σε υψηλότερο εύρος για να αποφύγετε τη μετακίνηση αντικειμένων σε υψηλότερες γενιές.

Σημειώστε ότι όταν έχετε καταστροφέα στην τάξη σας, ο χρόνος εκτέλεσης το αντιμετωπίζει ως μέθοδο οριστικοποίησης (). Δεδομένου ότι η ολοκλήρωση είναι δαπανηρή, θα πρέπει να χρησιμοποιείτε καταστροφές μόνο εάν χρειάζεται - όταν έχετε κάποιους πόρους στην τάξη σας που θα χρειαζόταν να καθαρίσετε. Όταν έχετε έναν οριστικοποιητή στην τάξη σας, αντικείμενα αυτών των τάξεων μετακινούνται στην ουρά οριστικοποίησης. Εάν τα αντικείμενα είναι προσβάσιμα, μετακινούνται στην ουρά "Freachable". Το GC ανακτά τη μνήμη που καταλαμβάνεται από αντικείμενα που δεν είναι προσβάσιμα. Περιοδικά, το GC ελέγχει εάν τα αντικείμενα που βρίσκονται στην ουρά "Freachable" είναι προσβάσιμα. Εάν δεν είναι προσβάσιμα, η μνήμη που καταλαμβάνεται από αυτά τα αντικείμενα ανακτάται. Έτσι, είναι προφανές ότι τα αντικείμενα που βρίσκονται στην ουρά "Freachable" θα χρειαστούν περισσότερο χρόνο για να καθαριστούν από τον συλλέκτη απορριμμάτων. Είναι κακή πρακτική να έχετε άδειους καταστροφείς στην τάξη C # σας, καθώς αντικείμενα τέτοιων τάξεων θα μετακινηθούν στην ουρά οριστικοποίησης και, στη συνέχεια, στην ουρά "Freachable", εάν χρειαστεί.

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

Η μέθοδος "Απόρριψη" από την άλλη πλευρά παρέχει μια "ντετερμινιστική εκκαθάριση" προσέγγιση για την εκκαθάριση πόρων στο .Net. Ωστόσο, η μέθοδος Dispose σε αντίθεση με τον οριστικοποιητή πρέπει να καλείται ρητά. Εάν έχετε ορίσει μια μέθοδο διάθεσης σε μια τάξη, πρέπει να βεβαιωθείτε ότι καλείται. Έτσι, η μέθοδος Dispose πρέπει να καλείται ρητά από τον κωδικό πελάτη. Τι γίνεται όμως αν ξεχάσετε να καλέσετε τη μέθοδο Dispose που εκτίθεται από μια τάξη που χρησιμοποιεί μη διαχειριζόμενους πόρους; Οι πελάτες μιας παρουσίας μιας κλάσης που εφαρμόζει τη διασύνδεση IDisposable θα πρέπει να καλέσουν ρητά τη μέθοδο διάθεσης. Σε αυτήν την περίπτωση, πρέπει να καλέσετε το Dispose από τον οριστικοποιητή. Αυτή η αυτόματη στρατηγική οριστικοποίησης οριστικοποιεί διασφαλίζει ότι οι μη διαχειριζόμενοι πόροι που χρησιμοποιούνται στον κώδικά σας καθαρίζονται.

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

Το ακόλουθο απόσπασμα κώδικα δείχνει πώς μπορείτε να εφαρμόσετε το μοτίβο Dispose Finalize στο C #.

προστατευμένο εικονικό κενό Διάθεση (διάθεση bool)

        {

εάν (απόρριψη)

            {

// γράψτε κώδικα για τον καθαρισμό διαχειριζόμενων αντικειμένων

            }

// γράψτε κώδικα για την εκκαθάριση μη διαχειριζόμενων αντικειμένων και πόρων

        }

Αυτή η παράμετρος μέθοδος διάθεσης μπορεί να κληθεί αυτόματα από τον καταστροφέα όπως φαίνεται στο παρακάτω απόσπασμα κώδικα.

~ Πόροι ()

        {

εάν (! διατίθεται)

            {

διάθεση = αλήθεια;

Απορρίψτε (false).

            }

        }

$config[zx-auto] not found$config[zx-overlay] not found