bnvdarklord Δημοσ. 12 Ιανουαρίου 2011 Δημοσ. 12 Ιανουαρίου 2011 Εστω οτι εχουμε μια κλάση Α και καποιες κλάσεις Β:Α και C:A. Στην main εχουμε δηλώσει το εξής Α x = new B(); Και καποια στιγμή καλείται μια μέθοδος μέσα στο Β η οποία με την σειρά της καλεί μια μέθοδο στην main η οποία κανει το εξής: x = new C(); To ερώτημα μου ειναι αν το Β καταστρέφεται, ή μενει στην μνήμη. Ευχαριστώ.
Evgenios1 Δημοσ. 12 Ιανουαρίου 2011 Δημοσ. 12 Ιανουαρίου 2011 http://msdn.microsoft.com/en-us/library/66x5fx1b.aspx The programmer has no control over when the destructor is called because this is determined by the garbage collector. The garbage collector checks for objects that are no longer being used by the application. If it considers an object eligible for destruction, it calls the destructor (if any) and reclaims the memory used to store the object. Destructors are also called when the program exits.
bnvdarklord Δημοσ. 12 Ιανουαρίου 2011 Μέλος Δημοσ. 12 Ιανουαρίου 2011 Ευχαριστώ. Οταν το πόσταρα ειχα παρατηρησει οτι η χρήση ram συνεχως ανεβαινει, αλλα τελικά καποιες φορές μειώνεται. Δηλαδή σε java/c# κτλ εφοσον εχεις garbage collecction δεν παιζουν memory leaks?
Directx Δημοσ. 12 Ιανουαρίου 2011 Δημοσ. 12 Ιανουαρίου 2011 Ευχαριστώ. Οταν το πόσταρα ειχα παρατηρησει οτι η χρήση ram συνεχως ανεβαινει, αλλα τελικά καποιες φορές μειώνεται. Δηλαδή σε java/c# κτλ εφοσον εχεις garbage collecction δεν παιζουν memory leaks? Εκ πρώτης όψεως μπορεί να πει κανείς ότι σε αυτά τα περιβάλλοντα δεν έχουμε το τυπικό "memory leak" όπως είναι γνωστό στην C & C++, όμως στην πραγματικότητα και εδώ πρέπει να είσαι προσεκτικός ώστε να μην κάνεις κατάχρηση των πόρων (ένα είδος "object overuse" ) οδηγώντας τον GC στα όρια του διότι σε αυτή την περίπτωση και η μνήμη της διεργασίας σου θα αυξηθεί αλλά και η απόδοση του προγράμματος σου θα μειωθεί καθώς ο GC θα προσπαθεί ανά τακτά χρονικά διαστήματα να αποδεσμεύσει (reclaim) μεγάλο αριθμό άχρηστων αντικειμένων. Για αυτό τον λόγο, η MS όσον αφορά την C# προτρέπει τους προγραμματιστές να κάνουν Dispose όσα αντικείμενα το υποστηρίζουν και δεν χρειάζονται πια, ώστε να διευκολύνουν τον GC επί το έργο, όσον αφορά την Java και ειδικά σε πλατφόρμες με περιορισμένους πόρους (πχ. J2ME για κινητά ή Android, WP7 κλπ) προτείνεται επίσης η επαναχρησιμοποίηση όσο το δυνατόν περισσότερων αντικειμένων ώστε να αποφεύγεται η χρονοβόρα κατασκευή τους (new) αλλά και η μετέπειτα διαγραφή τους (reclaim) από τον GC, συμβουλή που μπορεί φυσικά να εφαρμοστεί και στην C#. Με αυτά υπόψη (σεβασμός στο GC - όχι κατάχρηση του επειδή κάνει μόνος του το χαμαλίκι της διαχείρισης μνήμης), ο προγραμματισμός σε αυτά τα περιβάλλοντα είναι πραγματικά "όνειρο" για τους περισσότερους προγραμματιστές αφού η διαχείριση μνήμης γίνεται αυτόματα και δίχως ιδιαίτερα προβλήματα απόδοσης στις περισσότερες εφαρμογές.
Evgenios1 Δημοσ. 12 Ιανουαρίου 2011 Δημοσ. 12 Ιανουαρίου 2011 Εκ πρώτης όψεως μπορεί να πει κανείς ότι σε αυτά τα περιβάλλοντα δεν έχουμε το τυπικό "memory leak" όπως είναι γνωστό στην C & C++, όμως στην πραγματικότητα και εδώ πρέπει να είσαι προσεκτικός ώστε να μην κάνεις κατάχρηση των πόρων (ένα είδος "object overuse" ) οδηγώντας τον GC στα όρια του διότι σε αυτή την περίπτωση και η μνήμη της διεργασίας σου θα αυξηθεί αλλά και η απόδοση του προγράμματος σου θα μειωθεί καθώς ο GC θα προσπαθεί ανά τακτά χρονικά διαστήματα να αποδεσμεύσει (reclaim) μεγάλο αριθμό άχρηστων αντικειμένων. Για αυτό τον λόγο, η MS όσον αφορά την C# προτρέπει τους προγραμματιστές να κάνουν Dispose όσα αντικείμενα το υποστηρίζουν και δεν χρειάζονται πια, ώστε να διευκολύνουν τον GC επί το έργο, όσον αφορά την Java και ειδικά σε πλατφόρμες με περιορισμένους πόρους (πχ. J2ME για κινητά ή Android, WP7 κλπ) προτείνεται επίσης η επαναχρησιμοποίηση όσο το δυνατόν περισσότερων αντικειμένων ώστε να αποφεύγεται η χρονοβόρα κατασκευή τους (new) αλλά και η μετέπειτα διαγραφή τους (reclaim) από τον GC, συμβουλή που μπορεί φυσικά να εφαρμοστεί και στην C#. Με αυτά υπόψη (σεβασμός στο GC - όχι κατάχρηση του επειδή κάνει μόνος του το χαμαλίκι της διαχείρισης μνήμης), ο προγραμματισμός σε αυτά τα περιβάλλοντα είναι πραγματικά "όνειρο" για τους περισσότερους προγραμματιστές αφού η διαχείριση μνήμης γίνεται αυτόματα και δίχως ιδιαίτερα προβλήματα απόδοσης στις περισσότερες εφαρμογές. Πολυ σωστος!!! Να σιμειωσω: IDispose δουλευει με το keyword using px > ... using (Somthing som = new Somthing()) { .... }//<-- καλειται η Dispose ...
Directx Δημοσ. 12 Ιανουαρίου 2011 Δημοσ. 12 Ιανουαρίου 2011 Πολυ σωστος!!! Να σιμειωσω: IDispose δουλευει με το keyword using px > ... using (Somthing som = new Somthing()) { .... }//<-- καλειται η Dispose ... Yeap! Επ' ευκαιρίας να σημειώσω ότι είναι ένα εύχρηστο ιδίωμα το οποίο όσοι έρχονται από τον C++ Builder όπου έχουν συνηθίσει να αποδεσμεύουν τα αντικείμενα της VCL (ας πούμε ο πατέρας του .NET σε native non managed μορφή) είτε μέσο του finally{ } block ή αυτόματα μέσο του auto_ptr (όπου εξυπηρετεί η χρήση του) καλό είναι να το συνηθίσουν!
bnvdarklord Δημοσ. 13 Ιανουαρίου 2011 Μέλος Δημοσ. 13 Ιανουαρίου 2011 Δεν κατάλαβα αυτο με το IDispose.
Directx Δημοσ. 13 Ιανουαρίου 2011 Δημοσ. 13 Ιανουαρίου 2011 To Dispose είναι μια μέθοδος η οποία όταν κληθεί υποδεικνύει στο αντικείμενο (κλάση) που το υλοποιεί πως πρέπει να αποδεσμεύσει τους πόρους που χρησιμοποιεί. Ως μέθοδος κληρονομείται από το IDisposable Interface και καλείται αυτόματα μέσο της εντολής using που προσφέρει η C#. Φυσικά αν είναι επιθυμητό τίποτα δεν μας εμποδίζει από το να καλέσουμε μόνοι μας (με το χέρι δηλαδή) το Dispose που τυχόν προσφέρει το αντικείμενο / κλάση. Ακολουθεί ένα μικρό παράδειγμα σε C# το οποίο παρουσιάζει διάφορους τρόπους χρήσης του Dispose αλλά και υλοποίησης του (μέσο του IDisposable Interface) από ένα δικό μας αντικείμενο / κλάση (MyDrawRect): > /* Dispose Demo, DX */ using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace DisposeDemo { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Paint(object sender, PaintEventArgs e) { /* #1 - Αποδέσμευση Brush με try{ }finally{ } μπλοκ */ Brush MyBrush1 = null; try { /* Κατασκευή ενός νέου Brush με χρώμα Red */ MyBrush1 = new System.Drawing.SolidBrush(Color.Red); /* Σχεδίαση ενός παραλληλόγραμμου διαστάσεων 100x100 px στην φόρμα */ e.Graphics.FillRectangle(MyBrush1, 0, 0, 100, 100); } finally { /* * Αποδέσμευση του MyBrush1 σε κάθε περίπτωση (ακόμα και αν παρουσιασθεί * σφάλμα) αν είναι δεσμευμένο (!= null). */ if (MyBrush1 != null) MyBrush1.Dispose(); } /* * #2 - Αποδέσμευση Brush με using(){ } * * Το using θα καλέσει αυτόματα, σε κάθε περίπτωση (ακόμα και αν παρουσιασθεί * σφάλμα), το .Dispose του MyBrush2 καθώς το finally υπονοείται. */ using (Brush MyBrush2 = new System.Drawing.SolidBrush(Color.Green)) { /* Σχεδίαση ενός παραλληλόγραμμου διαστάσεων 100x100 px στην φόρμα */ e.Graphics.FillRectangle(MyBrush2, 100, 0, 100, 100); } /* * #3 - Χρήση using από δική μας κλάση * * Το using θα καλέσει αυτόματα το Dispose της κλάσης MyDrawRect το οποίο * προσφέρεται μέσο του IDisposable Interface που υλοποιεί. */ using (MyDrawRect DrawRect = new MyDrawRect(200, 0, 100, 100, Color.Blue)) { DrawRect.Draw(e.Graphics); } /* * #4 - Αποδέσμευση Brush δίχως try{}finally{ } ή using (επικίνδυνο!) * * Κατασκευή ενός νέου Brush με χρώμα Yellow. */ Brush MyBrush3 = new System.Drawing.SolidBrush(Color.Yellow); /* Σχεδίαση ενός παραλληλόγραμμου διαστάσεων 100x100 px στην φόρμα */ e.Graphics.FillRectangle(MyBrush3, 300, 0, 100, 100); /* Αποδέσμευση MyBrush κατευθείαν (αν παρουσιασθεί σφάλμα δεν αποδεσμεύεται άμεσα)! */ MyBrush3.Dispose(); } /* Μια κλάση που προσφέρει Dispose (μέσο του IDisposable Interface) */ class MyDrawRect : IDisposable { System.Drawing.SolidBrush MyBrush = null; int X, Y, W, H; Color C; public MyDrawRect(int X, int Y, int W, int H, Color C) { // Φόρτωμα θέσης παραλληλόγραμμου this.X = X; this.Y = Y; // Φόρτωμα διαστάσεων παραλληλόγραμου this.W = W; this.H = H; // Φόρτωμα χρώματος παραλληλόγραμμου this.C = C; // Κατασκευή Brush χρώματος παραλληλόγραμμου MyBrush = new SolidBrush(C); } public void Draw(Graphics g) { // Σχεδίαση παραλληλόγραμμου σε ένα Graphics (DC) g.FillRectangle(MyBrush, X, Y, W, H); } // Μέθοδος του IDisposable Interface, ώστε η κλάση να είναι συμβατή με το using ;-) public void Dispose() { // Αποδέσμευση πόρων κλάσης if (MyBrush != null) MyBrush.Dispose(); } } } } ΕΞΟΔΟΣ: Uploaded with ImageShack.us Υ.Γ. Στον παραπάνω κώδικα προϋποθέτω πως υπάρχει δηλωμένο στην φόρμα ένα Paint event ονόματι "Form1_Paint", επίσης ο κώδικας δεν είναι βελτιστοποιημένος καθώς σε ένα κανονικό πρόγραμμα δεν είναι συνετή η συνεχόμενη δέσμευση / αποδέσμευση αντικειμένων κατά το paint, όμως αρκεί για να παρουσιασθεί η έννοια του Dispose.
Προτεινόμενες αναρτήσεις
Αρχειοθετημένο
Αυτό το θέμα έχει αρχειοθετηθεί και είναι κλειστό για περαιτέρω απαντήσεις.