moukoublen Δημοσ. 13 Οκτωβρίου 2012 Δημοσ. 13 Οκτωβρίου 2012 Ξαφνικά βρέθηκα "περικυκλωμένος" από αμφιβολίες για το αν έχω κατανοήσει σωστά τον κύκλο ζωής των αντικειμένων στο .NET. Θέλω να ξεκινήσω με αυτό: Διαβάζω εδώ If disposable object x contains or "wraps" or "possesses" disposable object y, x's Dispose method automatically calls y's Dispose method - unless instructed otherwise. Κάνω λοιπόν το εξής. > class T1 : IDisposable { public void Dispose() { Console.WriteLine("T1 Disposed"); } } class T2 : IDisposable { private T1 ts = new T1(); public void Dispose() { Console.WriteLine("T2 Disposed"); } } class Program { static void Main(string[] args) { using (var d = new T2()) { } } } Και η έξοδος που έχω είναι T2 Disposed Και τίποτε άλλο. Τι γίνεται;... Και γενικότερα (από κει που μου ξεκίνησε η απορία). Έστω ότι έχω μια φόρμα windows forms. Και μέσω ενός κουμπιού ανοίγει με ShowDialog μία άλλη φόρμα που έχει 1 DataTable εσωτερικά της (το οποίο είναι disposable) (δε μιλώ για τα gui components). Όταν θα κλείσει ο χρήστης τη φόρμα αυτή, το table θα γίνει dispose ή όχι; Και εάν όχι, κάθε φορά που θα ανοίγω το dialog αυτό, θα κρέμονται στη μνήμη DataTables; Ευχαριστώ εκ των προτέρων.
MitsakosGR Δημοσ. 13 Οκτωβρίου 2012 Δημοσ. 13 Οκτωβρίου 2012 Θα γίνει dispose κανονικά μόλις το συλλέξει ο garbage collector. Αυτό είναι το νόημα του IDisposable. Όταν χειρίζεσαι unsafe code το κάνεις IDisposable για να απελευθερώνεις όση μνήμη δέσμευσες. Αν δεν καλέσεις μόνος σου την Dispose() την καλεί αυτόματα ο Garbage Collector.
albNik Δημοσ. 13 Οκτωβρίου 2012 Δημοσ. 13 Οκτωβρίου 2012 Ποτέ δεν καλεί τη Dispose() o Garbage Collector. Στο παράδειγμα με Form o designer έχει φτιάξει αυτόν τον κώδικα, (Form1.Designer.cs) > protected override void Dispose(bool disposing) { if(disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } που καλείται όταν κλείνει η Φορμα. Αν δεν έχει προστεθεί στα components to DataTable (π.χ. είναι local σε μια συνάρτηση) δε θα γίνει Dispose()) If disposable object x contains or "wraps" or "possesses" disposable object y, x's Dispose method automatically calls y's Dispose method - unless instructed otherwise. Αυτοί είναι κανόνες που σέβεται το .ΝΕΤ και συνιστώνται γενικά. Απλή συνάρτηση σαν όλες της άλλες είναι.
moukoublen Δημοσ. 13 Οκτωβρίου 2012 Μέλος Δημοσ. 13 Οκτωβρίου 2012 Ποτέ δεν καλεί τη Dispose() o Garbage Collector. Αν δεν έχει προστεθεί στα components to DataTable (π.χ. είναι local σε μια συνάρτηση) δε θα γίνει Dispose()) ... Αυτοί είναι κανόνες που σέβεται το .ΝΕΤ και συνιστώνται γενικά. Απλή συνάρτηση σαν όλες της άλλες είναι. Δε μιλάω για το DataGridView που είναι (visual) component της φόρμας. Μιλάω για το DataTable που είναι απλά ένα disposable αντικείμενο (και είναι παράδειγμα). Και η απορία μου είναι οτι αν ισχύει αυτό που έχω στα quote τότε όταν καλείται η dispose του Τ2 θα πρέπει να καλείται και η dispose του πεδίου T1 που περιέχει (σύμφωνα με τον κανόνα που παρέθεσα) αλλά δεν βλέπω να συμβαίνει. Άρα θα πρέπει κάθε disposable αντικείμενο το οποίο δεν είναι μέσα σε ενα using να καλείτε με το χέρι το dispose του κάποια στιγμή οπωσδήποτε. Άρα ακόμα και αν υπάρχουν 2 - 3 DataTable (που μπορεί να χρησιμοποιούνται σαν datasource για κάποια DataGridView) θα πρέπει έστω στο on_closed event να τα κάνει κανείς dispose διαφορετικά "κρέμονται" στη μνήμη; Αυτή είναι η απορία μου. Κοινώς είναι λάθος αυτό το που παρέθεσα από το βιβλίο;
moukoublen Δημοσ. 13 Οκτωβρίου 2012 Μέλος Δημοσ. 13 Οκτωβρίου 2012 Στην C# δεν εχεις την εννοια του destructor Σύμφωνοι (αν και υπάρχει αλλά δεν είναι απαραίτητος αν έχεις απλά .net αντικείμενα στην class). Αλλά δεν μιλάω για destructor. Για τα disposable αντικείμενα μιλάω. Και για το αν και καταπόσο ισχύει αυτό που παρέθεσα στο quote.
albNik Δημοσ. 13 Οκτωβρίου 2012 Δημοσ. 13 Οκτωβρίου 2012 Και η απορία μου είναι οτι αν ισχύει αυτό που έχω στα quote τότε όταν καλείτε η dispose του Τ2 θα πρέπει να καλείται και η dispose του πεδίου T1 που περιέχει (σύμφωνα με τον κανόνα που παρέθεσα) αλλά δεν βλέπω να συμβαίνει. Αυτό δεν έγινε διότι δεν σεβαστικές τους κανόνες στα quote. Εσύ έπρεπε μέσα στο Dispose(){ } της Τ2 να προσθέσεις ts.Dispose(). Η Dispose() δεν είναι destructor, ούτε καλείται από μόνη της.
παπι Δημοσ. 13 Οκτωβρίου 2012 Δημοσ. 13 Οκτωβρίου 2012 Σύμφωνοι (αν και υπάρχει αλλά δεν είναι απαραίτητος αν έχεις απλά .net αντικείμενα στην class). Αλλά δεν μιλάω για destructor. Για τα disposable αντικείμενα μιλάω. Και για το αν και καταπόσο ισχύει αυτό που παρέθεσα στο quote. Ε τοτε γιατι να υπαρχει αυτη η συμπεριφορα που λες; το dispose ειναι ενα interface που που καλειται σε try και using τιποτα αλλο
albNik Δημοσ. 13 Οκτωβρίου 2012 Δημοσ. 13 Οκτωβρίου 2012 Στην C# δεν εχεις την εννοια του destructor Βεβαίως και έχει > class MyClass { ~MyClass() { Console.WriteLine("destructor"); } } static class Program { static void Main() { MyClass c = new MyClass(); } }
moukoublen Δημοσ. 13 Οκτωβρίου 2012 Μέλος Δημοσ. 13 Οκτωβρίου 2012 Αυτό δεν έγινε διότι δεν σεβαστικές τους κανόνες στα quote. Εσύ έπρεπε μέσα στο Dispose(){ } της Τ2 να προσθέσεις ts.Dispose(). Η Dispose() δεν είναι destructor, ούτε καλείται από μόνη της. Να το δεχτώ και έτσι πρέπει να είναι. Αλλά γιατί λέει x's Dispose method automatically calls y's Dispose method αν εννοεί οτι πρέπει να το γράψεις εσύ;
παπι Δημοσ. 13 Οκτωβρίου 2012 Δημοσ. 13 Οκτωβρίου 2012 Να το δεχτώ και έτσι πρέπει να είναι. Αλλά γιατί λέει αν εννοεί οτι πρέπει να το γράψεις εσύ; Δες msdn
albNik Δημοσ. 13 Οκτωβρίου 2012 Δημοσ. 13 Οκτωβρίου 2012 Να το δεχτώ και έτσι πρέπει να είναι. Αλλά γιατί λέει αν εννοεί οτι πρέπει να το γράψεις εσύ; "The Framework follows a set of de facto rules" ... λέει.
moukoublen Δημοσ. 13 Οκτωβρίου 2012 Μέλος Δημοσ. 13 Οκτωβρίου 2012 Ε τοτε γιατι να υπαρχει αυτη η συμπεριφορα που λες; το dispose ειναι ενα interface που που καλειται σε try και using τιποτα αλλο Μα η απορία μου είναι στο αν ισχύει το quote που λέει ότι καλείται αυτόματα αν στο dispose ενός disposable αντικειμένου που περιέχει ένα άλλο. - Άρα αν έχεις μια class που περιέχει κάποια DIsposable objects θα πρέπει στον finalizer (destructor) να καλέσεις και το dispose αυτών των disposabe objects ώστε οτα το μαζέψει ο garbage collector να κληθεί και το dispose αυτών. Αντίστοιχα στη φόρμα στο on_close ή κάπου παρόμοια πρέπει να κάνεις το ίδιο αν έχεις προσθέσει disposable αντικείμενα. Πάντως θέλω να επιμείνω στην ερώτηση. Για κάθε DataTable (επαναλαμβάνω δε μιλάω για το visual component DataGridView) που μπορείς να φτιάξεις σε μία φόρμα, πρέπει να καλείται το Dispose χειροκίνητα; Και ΑΝ ναι πρέπει να γίνουν dispose και όλα τα DataColumn s ξεχωριστά; Υ.Γ. Πάντως για να δείτε γιατί μπερδεύομαι στο msdn εδώ κάτω κάτω εκεί που λέει Dispose vs. Close Method Usage (άσχετο με την απορία μου) λέει ... and standard .NET Framework garbage collection calls the Dispose method to free any resources associated with the object from memory....
albNik Δημοσ. 13 Οκτωβρίου 2012 Δημοσ. 13 Οκτωβρίου 2012 Η Dispose() μέσα σε destructor θέλει λίγο παραπάνω δουλειά. http://stackoverflow.com/questions/628752/why-call-disposefalse-in-the-destructor Συνήθως την καλείς πιο γρήγορα. Το destructor μπορεί να αργήσει να κληθεί. Ίσως όταν τερματίσει το exe.
παπι Δημοσ. 13 Οκτωβρίου 2012 Δημοσ. 13 Οκτωβρίου 2012 Μα η απορία μου είναι στο αν ισχύει το quote που λέει ότι καλείται αυτόματα αν στο dispose ενός disposable αντικειμένου που περιέχει ένα άλλο. Οχι βεβαια!!!! Φαντασου να εχεις ενα resource στην main και αυτο να το περνας σε μια φορμα (απλο reference). Τοτε οταν κλεισεις την φορμα το resource θα απελευθερωθει, κατι που σιγουρα δεν θελεις εφοσον ειναι reference
Προτεινόμενες αναρτήσεις
Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε
Πρέπει να είστε μέλος για να αφήσετε σχόλιο
Δημιουργία λογαριασμού
Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!
Δημιουργία νέου λογαριασμούΣύνδεση
Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.
Συνδεθείτε τώρα