Ρύθμιση αντικείμενα στην Null / Τίποτα μετά τη χρήση στην ΝΕΤ

ψήφοι
173

Θα πρέπει να ορίσετε όλα τα αντικείμενα για να null( Nothingσε VB.NET), αφού έχετε τελειώσει μαζί τους;

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

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

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

MSDN άρθρα ποτέ δεν το κάνουμε αυτό με παραδείγματα και σήμερα κάνω αυτό, όπως δεν μπορώ να δω τη ζημιά. Ωστόσο, έχω έρθει σε ένα μίγμα απόψεων, ώστε τυχόν παρατηρήσεις είναι χρήσιμες.

Δημοσιεύθηκε 05/08/2008 στις 21:14
πηγή χρήστη
Σε άλλες γλώσσες...                            


13 απαντήσεις

ψήφοι
66

Karl είναι απολύτως σωστό, δεν υπάρχει ανάγκη να ρυθμίσετε αντικείμενα για να άκυρη μετά τη χρήση. Αν ένα αντικείμενο υλοποιεί IDisposable, απλά φροντίστε να καλέσετε IDisposable.Dispose()όταν τελειώσετε με αυτό το αντικείμενο (τυλιγμένο σε μια try.. finally, ή, ένα using()μπλοκ). Αλλά ακόμα και αν δεν θυμάστε να καλέσετε Dispose(), η μέθοδος finaliser στο αντικείμενο θα πρέπει να καλούν Dispose()για εσάς.

Σκέφτηκα ότι αυτό ήταν μια καλή θεραπεία:

Σκάβοντας σε IDisposable

και αυτό

Κατανόηση IDisposable

Δεν υπάρχει κανένα νόημα να προσπαθούμε να μαντέψουμε το δεύτερο το GC και τις στρατηγικές διαχείρισης της επειδή είναι μόνος ρύθμιση και αδιαφανές. Υπήρξε μια καλή συζήτηση για τις εσωτερικές διεργασίες με Jeffrey Ρίχτερ στο Dot Net Rocks εδώ: Jeffrey Ρίχτερ στο μοντέλο μνήμης των Windows βιβλίου και Richters CLR μέσω C # κεφάλαιο 20 έχει μια πολύ καλή θεραπεία:

Απαντήθηκε 05/08/2008 στις 21:56
πηγή χρήστη

ψήφοι
33

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

π.χ

void foo()
{
    var someType = new SomeType();
    someType.DoSomething();
    // someType is now eligible for garbage collection         

    // ... rest of method not using 'someType' ...
}

θα επιτρέψει στο αντικείμενο που αναφέρεται από sometype να GC'd μετά την κλήση για να «doSomething», αλλά

void foo()
{
    var someType = new SomeType();
    someType.DoSomething();
    // someType is NOT eligible for garbage collection yet
    // because that variable is used at the end of the method         

    // ... rest of method not using 'someType' ...
    someType = null;
}

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

Απαντήθηκε 15/08/2008 στις 15:43
πηγή χρήστη

ψήφοι
15

Όχι δεν null αντικείμενα. Μπορείτε να ελέγξετε έξω http://codebetter.com/blogs/karlseguin/archive/2008/04/27/foundations-of-programming-pt-7-back-to-basics-memory.aspx για περισσότερες πληροφορίες, αλλά και τον καθορισμό πράγματα με μηδενική δεν θα κάνει τίποτα, εκτός από βρώμικα τον κωδικό σας.

Απαντήθηκε 05/08/2008 στις 21:23
πηγή χρήστη

ψήφοι
7

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

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

this.myField.Dispose();
// ... at some later time
this.myField.DoSomething();

Είναι καλό να null το πεδίο μετά την απόρριψη αυτή, και να πάρει το δικαίωμα NullPtrEx στη γραμμή όπου το πεδίο χρησιμοποιείται και πάλι. Διαφορετικά, μπορεί να τρέξει σε κάποιο αινιγματικό bug κάτω από τη γραμμή (ανάλογα με το τι ακριβώς κάνει doSomething).

Απαντήθηκε 09/08/2008 στις 12:16
πηγή χρήστη

ψήφοι
7

Επίσης:

using(SomeObject object = new SomeObject()) 
{
  // do stuff with the object
}
// the object will be disposed of
Απαντήθηκε 05/08/2008 στις 21:37
πηγή χρήστη

ψήφοι
6

Οι πιθανότητες είναι ότι ο κωδικός σας δεν είναι δομημένη αρκετά καλά, εάν αισθάνεστε την ανάγκη να nullμεταβλητές.

Υπάρχουν διάφοροι τρόποι για να περιορίσει το πεδίο εφαρμογής μιας μεταβλητής:

Όπως αναφέρει ο Steve Tranby

using(SomeObject object = new SomeObject()) 
{
  // do stuff with the object
}
// the object will be disposed of

Ομοίως, μπορείτε απλά να χρησιμοποιήσετε αγκύλες:

{
    // Declare the variable and use it
    SomeObject object = new SomeObject()
}
// The variable is no longer available

Θεωρώ ότι η χρήση αγκύλες χωρίς οποιαδήποτε «επικεφαλίδα» για να καθαρίσει πραγματικά τον κώδικα και να βοηθήσει να γίνει πιο κατανοητό.

Απαντήθηκε 09/08/2008 στις 13:13
πηγή χρήστη

ψήφοι
5

Σε γενικές γραμμές, δεν χρειάζεται να ρυθμιστεί σε null. Αλλά ας υποθέσουμε ότι έχετε ένα Reset λειτουργικότητα στην τάξη σας.

Στη συνέχεια, μπορείτε να το κάνετε, γιατί δεν θέλετε να καλέσετε διαθέτει δύο φορές, δεδομένου ότι ορισμένες από τις Απορρίψτε δεν μπορεί να εφαρμοστεί σωστά και να ρίξει System.ObjectDisposed εξαίρεση.

private void Reset()
{
    if(_dataset != null)
    {
       _dataset.Dispose();
       _dataset = null;
    }
    //..More such member variables like oracle connection etc. _oraConnection
 }
Απαντήθηκε 17/04/2012 στις 09:55
πηγή χρήστη

ψήφοι
4

Η μόνη φορά που θα πρέπει να ορίσετε μια μεταβλητή για να null είναι όταν η μεταβλητή δεν βγαίνουν από το πεδίο εφαρμογής και δεν χρειάζεται πλέον τα δεδομένα που σχετίζονται με αυτό. Διαφορετικά δεν υπάρχει ανάγκη.

Απαντήθηκε 05/08/2008 στις 21:32
πηγή χρήστη

ψήφοι
3

αυτό το είδος της «δεν υπάρχει καμία ανάγκη να ρυθμίσετε αντικείμενα για να άκυρη μετά τη χρήση» δεν είναι απολύτως ακριβής. Υπάρχουν φορές που πρέπει να NULL τη μεταβλητή μετά την απόρριψη αυτή.

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

Ξεχωριστό από αυτό το πολύ πρακτικό πρότυπο LazyLoad.

Πείτε έχω και τεκμηριώθηκε ObjAτης class A. Class Aέχει μια δημόσια περιουσία που ονομάζεται PropBτου class B.

Εσωτερικά, PropBχρησιμοποιεί την ιδιωτική μεταβλητή _Bκαι προεπιλογές σε null. Όταν PropB.Get()χρησιμοποιείται, ελέγχει για να δει αν _PropBείναι άκυρη και αν είναι, ανοίγει τους πόρους που απαιτούνται για την υπόσταση σε μια Bσε _PropB. Στη συνέχεια επιστρέφει _PropB.

Για την εμπειρία μου, αυτό είναι ένα πραγματικά χρήσιμο κόλπο.

Όταν η ανάγκη για μηδενική μπαίνει είναι εάν επαναφέρετε ή να αλλάξετε μια κατά κάποιο τρόπο ότι το περιεχόμενο της _PropBήταν το παιδί από τις προηγούμενες τιμές της A, θα πρέπει να Απορρίψτε ΚΑΙ null έξω _PropBέτσι LazyLoad να επαναφέρετε για να πάρει τη σωστή αξία εάν ο κωδικός απαιτεί αυτό.

Αν το μόνο που κάνουμε _PropB.Dispose()και λίγο μετά αναμένουμε η μηδενική ελέγχου για LazyLoad να πετύχει, δεν θα είναι μηδενική, και θα πρέπει να ψάχνει σε μπαγιάτικο δεδομένων. Στην πραγματικότητα, θα πρέπει να το null μετά από Dispose()ακριβώς για να είναι σίγουρος.

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

Τελικά, το μεταβίβασε το ακίνητο θα null έξω, αλλά αυτό ήταν μη-ντετερμινιστικό από την πλευρά μου.

Ο πυρήνας λόγος, όπως dbkk εννοεί είναι ότι η μητρική δοχείο ( ObjAμε PropB) κρατά την περίπτωση _PropBστο πεδίο εφαρμογής, παρά το Dispose().

Απαντήθηκε 11/04/2012 στις 02:12
πηγή χρήστη

ψήφοι
1

Ρίξτε μια ματιά σε αυτό το άρθρο, καθώς: http://www.codeproject.com/KB/cs/idisposable.aspx

Για το μεγαλύτερο μέρος, θέτοντας ένα αντικείμενο με μηδενική έχει καμία επίδραση. Η μόνη φορά που θα πρέπει να είναι σίγουρος για να το κάνει είναι εάν εργάζεστε με ένα «μεγάλο αντικείμενο», το οποίο είναι ένα μεγαλύτερο από 84K σε μέγεθος (όπως bitmaps).

Απαντήθηκε 17/08/2008 στις 05:46
πηγή χρήστη

ψήφοι
1

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

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

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

Απαντήθηκε 05/08/2008 στις 21:46
πηγή χρήστη

ψήφοι
0

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

Προσωπικά, έχω συχνά ορίζεται ρητά μεταβλητές με μηδενική όταν είμαι γίνει με αυτούς ως μια μορφή αυτο τεκμηρίωσης. Δεν δηλώνουν, χρησιμοποιούν, στη συνέχεια, ορίστε την σε κενή αργότερα - Ι null αμέσως μετά δεν είναι απαραίτητη. Λέω, ρητά, «είμαι επίσημα γίνει με σας ... να φύγει ...»

Είναι ακυρώνει αναγκαία σε μια γλώσσα GC'd; Όχι Είναι χρήσιμο για το GC; Ίσως ναι, ίσως όχι, δεν γνωρίζουμε με βεβαιότητα, από το σχεδιασμό πραγματικά δεν μπορώ να το ελέγξει, και ανεξάρτητα από τη σημερινή απάντηση με αυτή την έκδοση ή ότι, στο μέλλον εφαρμογές GC θα μπορούσε να αλλάξει την απάντηση πέρα από τον έλεγχό μου. Πλέον, αν / όταν μηδενισμού έχει βελτιστοποιηθεί έξω είναι λίγο περισσότερο από ένα φανταχτερό σχόλιο αν θέλετε.

Μπορώ να καταλάβω αν κάνει η πρόθεσή μου σαφέστερη στην επόμενη φτωχούς ανόητος που ακολουθεί τα βήματά μου, και αν «θα μπορούσε» ενδεχομένως να βοηθήσει GC μερικές φορές, τότε αξίζει τον κόπο για μένα. Κυρίως αυτό με κάνει να αισθάνομαι τακτοποιημένο και καθαρό, και Mongo αρέσει να αισθάνονται τακτοποιημένο και καθαρό. :)

Θα το δει κανείς σαν αυτό: υπάρχουν γλώσσες προγραμματισμού για να αφήσουμε τους ανθρώπους να δώσουν άλλους ανθρώπους μια ιδέα προθέσεων και compiler αίτηση δουλειά του τι πρέπει να κάνουμε - ο compiler μετατρέπει το αίτημα αυτό σε μια διαφορετική γλώσσα (μερικές φορές αρκετές) για ένα CPU - η CPU (ες) θα μπορούσε να δώσει μια δεκάρα τι γλώσσα που χρησιμοποιείται, τις ρυθμίσεις σας καρτέλα, σχόλια, υφολογική έμφαση, τα ονόματα των μεταβλητών, κλπ - η CPU είναι όλα σχετικά με τη ροή bit που λέει ό, τι καταγράφει και κώδικες λειτουργίας και θέσεις μνήμης για να παίζω. Πολλά πράγματα γραμμένα σε κώδικα δεν μετατρέπονται σε αυτό που καταναλώνεται από την CPU με τη σειρά που έχει καθοριστεί. C μας, C ++, C #, Lisp, Βαβέλ, συναρμολόγησης ή οτιδήποτε άλλο είναι η θεωρία και όχι την πραγματικότητα, γράφεται ως μια δήλωση της εργασίας. Αυτό που βλέπετε δεν είναι αυτό που παίρνετε, ναι, ακόμη και σε γλώσσα μηχανής.

Καταλαβαίνω τη νοοτροπία του «περιττά πράγματα» (όπως κενές γραμμές) «δεν είναι παρά το θόρυβο και την ακαταστασία τον κώδικα.» Αυτό μου ήταν νωρίτερα στην καριέρα μου? Είμαι απόλυτα πάρει αυτό. Στο σημείο αυτό κλίνει προς αυτό το οποίο κάνει κωδικό σαφέστερη. Δεν είναι σαν να είμαι προσθέτοντας ακόμα 50 γραμμές «θόρυβο» στα προγράμματα μου - είναι μερικές γραμμές εδώ ή εκεί.

Υπάρχουν εξαιρέσεις σε κάθε κανόνα. Σε σενάρια με πτητική μνήμη, στατική μνήμη, συνθήκες του αγώνα, μονήρεις, η χρήση του «μπαγιάτικο» τα δεδομένα και όλα αυτού του είδους της σήψης, αυτό είναι διαφορετικό: Θα πρέπει να διαχειριστεί τη δική σας μνήμη, το κλείδωμα και ακυρώνει ως επίκαιρο, γιατί η μνήμη δεν είναι μέρος του η GC'd Σύμπαν - ελπίζω ο καθένας αντιλαμβάνεται ότι. Το υπόλοιπο του χρόνου με τις γλώσσες GC'd είναι θέμα στυλ και όχι ανάγκη ή μια εγγυημένη αύξηση της απόδοσης.

Στο τέλος της ημέρας, βεβαιωθείτε ότι έχετε κατανοήσει τι είναι επιλέξιμες για GC και τι όχι? κλειδαριά, απορρίψτε, και την εξουδετέρωση καταλλήλως? κερί για, κερί off? εισπνοή εκπνοή; και ό, τι άλλο μπορώ να πω: Αν αισθάνεται καλά, να το κάνει. απόσταση σε μίλια σας μπορεί να ποικίλει ... όπως θα έπρεπε ...

Απαντήθηκε 10/05/2016 στις 13:07
πηγή χρήστη

ψήφοι
-1

Μερικοί αντικείμενο ας υποθέσουμε ότι η .dispose()μέθοδος η οποία αναγκάζει τον πόρο που πρέπει να αφαιρεθεί από τη μνήμη.

Απαντήθηκε 05/08/2008 στις 21:21
πηγή χρήστη

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more