| Autor |
Beitrag |
thD
      
Beiträge: 33
Win 7, VirtualBox
C# (VS 2008)
|
Verfasst: Mi 16.12.09 15:37
Hallo Leute,
hab jetzt etwas mit Klassen, Konstruktoren und Destruktoren experimentiert.
Und jetzt habe ich drei Frage.
1) Wie setzte ich das Objekt inerhalb der Klasse Circle auf null?
2) Was bewirkt der Befehl GC.SuppressFinalize(this);, den habe ich nämlich irgendwo gelesen aber nicht verstanden.
Hier der Code:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132:
| static void Main(string[] args) { Circle kreis = new Circle(); Console.WriteLine("Kreisrechner 1.00"); Console.WriteLine(Environment.NewLine); Console.Write("Geben Sie einen beliebigen Radius ein: "); kreis.Radius = int.Parse(Console.ReadLine()); Console.WriteLine(Environment.NewLine); Console.WriteLine("Durchmesser: {0,8:f2}m\nUmfang: {1,13:f2}m\nFläche: {2,13:f2}m", kreis.Durchmesser, kreis.Umfang, kreis.Area); } }
public class Circle : IDisposable { private double radius; private double durchmesser; private double umfang; private double area; private int xcoordinate; private int ycoordinate; public const double PI = 3.14159; private bool disposed = true;
public Circle() {} public Circle(double radius) { this.Radius = radius; } public Circle(double radius, int xPos, int yPos) { this.Radius = radius; this.Xcoordinate = xPos; this.Ycoordinate = yPos; }
~Circle() { Dispose(); }
public void Dispose() { GC.SuppressFinalize(this); ; }
public double Radius { get { return this.radius; } set { this.disposed = false;
if (value >= 0) { this.radius = value; this.umfang = 2 * this.radius * PI; this.area = this.radius * this.radius * PI; } else Console.WriteLine("Unzulässige Angabe!"); } }
public double Durchmesser { get { return 2 * this.radius; } }
public double Umfang { get { return this.umfang; } }
public double Area { get { return this.area; } }
public int Xcoordinate { get { return this.Xcoordinate; } set { this.disposed = false; this.xcoordinate = value; } }
public int Ycoordinate { get { return this.ycoordinate; } set { this.disposed = false; this.ycoordinate = value; } } } } |
3) Eine Frage zum GC.
Ich weiß das man mit GC.Collection den GC einschaltet.
Ich weiß auch das man das eig nicht tun soll.
Ich nehme jetzt das beispiel ich mache ein Spiel. Jedes mal wenn der Spieler ins Menü geht soll sich der GC einschalten und wenn er auf Weiterspielen drückt soll er sich ausschalten.
Ist das ausschalten möglich? Macht man das so in aktuellen und Ressourcen-hungrigen Anwendungen?
Edit: Oder schaltet sich der GC sofort wieder aus wenn die Auslastung hoch geht?
mfG thD
|
|
Kha
      
Beiträge: 3803
Erhaltene Danke: 176
Arch Linux
Python, C, C++ (vim)
|
Verfasst: Mi 16.12.09 23:14
thD hat folgendes geschrieben : | | hab jetzt etwas mit Klassen, Konstruktoren und Destruktoren experimentiert. |
Experimentieren ist immer gut, nur zur Klarstellung: Dass du bei reinen CLR-Klassen, die also nichts mit Interop zu tun haben, weder DestruktorenFinalizer noch IDisposable brauchst, ist dir klar?
thD hat folgendes geschrieben : | | 1) Wie setzte ich das Objekt inerhalb der Klasse Circle auf null? |
Wozu wollte man das tun? Mal abgesehen davon, dass ich keine Sprache kenne, in der this überhaupt veränderbar ist  .
thD hat folgendes geschrieben : | | 2) Was bewirkt der Befehl GC.SuppressFinalize(this);, den habe ich nämlich irgendwo gelesen aber nicht verstanden. |
Da ich es nicht besser erklären können werde als MSDN, frage ich lieber mal, was du dort nicht verstehst  .
thD hat folgendes geschrieben : | | Ich nehme jetzt das beispiel ich mache ein Spiel. Jedes mal wenn der Spieler ins Menü geht soll sich der GC einschalten und wenn er auf Weiterspielen drückt soll er sich ausschalten. |
Wenn das Spiel mit wirklichem OO-Design programmiert ist, würde ich schätzen, dass du nach einer halben Minute eine OutOfMemoryException kassieren würdest  . Nein, der GC ist immer an.
_________________ >λ=
|
|
thD 
      
Beiträge: 33
Win 7, VirtualBox
C# (VS 2008)
|
Verfasst: Do 17.12.09 00:10
Kha hat folgendes geschrieben : | thD hat folgendes geschrieben : | | hab jetzt etwas mit Klassen, Konstruktoren und Destruktoren experimentiert. | Experimentieren ist immer gut, nur zur Klarstellung: Dass du bei reinen CLR-Klassen, die also nichts mit Interop zu tun haben, weder DestruktorenFinalizer noch IDisposable brauchst, ist dir klar? |
Ja mir war klar das ich hier keinen IDisposable und Finalizer brauche, war nur eine kleine Übung. Das verwendet man nur wenn die Objekte so viel Speicher fressen das das System am Ende ist, oder? Der GC räumt ja von selber auf, oder? Was wäre eine nicht reine CLR-Klasse? Was ist ein Interop? Ich habe mir ein Buch gekauft das nur 370 Seiten hat, da war das Kapitel etwas kurz. Also habe ich in OpenBooks nachgelesen. Dort steht allerdings nichts von Finalizer sondern Destruktor. Was ist der Unterschied?
Kha hat folgendes geschrieben : | thD hat folgendes geschrieben : | | 1) Wie setzte ich das Objekt inerhalb der Klasse Circle auf null? | Wozu wollte man das tun? Mal abgesehen davon, dass ich keine Sprache kenne, in der this überhaupt veränderbar ist . |
Das wollte ich nämlich in den Dispose() einbauen. Wenn der aufgerufen wird, wird automatisch das Objekt auf null gesetzt. Sollte man das so nicht machen? Und wie kann ich auf das aufrufende Objekt verweisen?
Kha hat folgendes geschrieben : | thD hat folgendes geschrieben : | | 2) Was bewirkt der Befehl GC.SuppressFinalize(this);, den habe ich nämlich irgendwo gelesen aber nicht verstanden. | Da ich es nicht besser erklären können werde als MSDN, frage ich lieber mal, was du dort nicht verstehst . |
Ich habe das bei OpenBooks gelesen: Dieser wird beim Aufruf als Argument die Referenz auf das Objekt übergeben, dessen Destruktor nicht mehr ausgeführt werden soll.(Wenn man Dispose() ein zweites mal aufruft)
Wie übergibt der etwas?
Kha hat folgendes geschrieben : | thD hat folgendes geschrieben : | | Ich nehme jetzt das beispiel ich mache ein Spiel. Jedes mal wenn der Spieler ins Menü geht soll sich der GC einschalten und wenn er auf Weiterspielen drückt soll er sich ausschalten. | Wenn das Spiel mit wirklichem OO-Design programmiert ist, würde ich schätzen, dass du nach einer halben Minute eine OutOfMemoryException kassieren würdest . Nein, der GC ist immer an. |
Aha, was haben Spiele für ein Design? Wenn man mit XNA arbeitet, arbeitet man dan nicht im OO-Stil?
Der GC ist immer an? Ich dachte nur unter den 2 Bedingungen:
-Wenn der Speicher so voll ist das, dass System nicht mehr kann.
-|| wenn die Anwendung keine Auslastung vorweist.
Jetzt hätte ich noch zwei Fragen:
Edit: - Du arbeitest sicherlich als Programmierer, oder? Hast du vor nach dem Zivi als Programmierer zu arbeiten?
Edit: -Wenn ja, was hast du für eine Ausbildung gemacht? Hast du studiert?
Sorry für die vielen Fragen, aber ich bin Neugierig  .
mfG thD
|
|
Kha
      
Beiträge: 3803
Erhaltene Danke: 176
Arch Linux
Python, C, C++ (vim)
|
Verfasst: Fr 18.12.09 01:13
thD hat folgendes geschrieben : | | Das verwendet man nur wenn die Objekte so viel Speicher fressen das das System am Ende ist, oder? Der GC räumt ja von selber auf, oder? |
Ich versuche es nochmal  : 100% managed Klassen brauchen nie einen Finalizer. Es gibt einfach nichts Sinnvolles, was er machen könnte, um den GC in irgendeiner Art zu unterstützen o.Ä.
thD hat folgendes geschrieben : | | Was wäre eine nicht reine CLR-Klasse? |
Alles, was unmanaged Ressourcen benutzt, also Code, der nicht auf der CLR läuft. Das sind meistens Funktionen der Windows-API oder sonstige DLL-Funktionen, die über P/Invoke importiert wurden.
Zum Beispiel ein GDI-Handle in Klassen wie Image: Der GC sieht beim Abräumen einer Instanz davon bloß ein Feld vom Typ IntPtr, kann aber unmöglich wissen, dass er darauf GdipDisposeImage aufrufen muss. Das muss der Entwickler ihm schon selbst sagen, nämlich über einen Finalizer.
Mit Handles ist das allerdings so eine Sache... wenn man nicht aufpasst, können die dem OS doch glatt ausgehen  . Damit die Freigabe nicht erst geschieht, wenn der GC anspringt, sondern wenn der Benutzer der Klasse weiß, dass er das Objekt nicht mehr benötigt, gibt es das IDisposable-Pattern. Nachdem auf diesem Weg alle unmanaged Ressourcen freigegeben wurden, gibt es keinen Grund mehr, den teuren Finalizer vom GC aufrufen zu lassen - schon sind wir bei SuppressFinalize.
thD hat folgendes geschrieben : | | Dort steht allerdings nichts von Finalizer sondern Destruktor. Was ist der Unterschied? |
Nur unterschiedliche Benennungen, siehe: en.wikipedia.org/wiki/Finalizer
thD hat folgendes geschrieben : | | Sollte man das so nicht machen? |
Gegenfrage: Was versprichst du dir davon?
thD hat folgendes geschrieben : | | Und wie kann ich auf das aufrufende Objekt verweisen? |
Ohne weiteres gar nicht, wo bliebe da die tolle Entkuppelung der OOP?
thD hat folgendes geschrieben : | | (Wenn man Dispose() ein zweites mal aufruft) |
Ein zweites Mal? Dispose ruft den Finalizer nicht selbst auf, ein direkter Aufruf ist in C# gar nicht möglich.
thD hat folgendes geschrieben : | | Wie übergibt der etwas? |
Hm? Der Methode wird doch etwas übergeben?
thD hat folgendes geschrieben : | | Wenn man mit XNA arbeitet, arbeitet man dan nicht im OO-Stil? |
XNA selbst ist objektorierentiert. Darauf, wie weit du im Rest des Projektes mit OOP gehst, hat das aber wenig Einfluss  . Ob zu komplexes OO-Design mit zu vielen Objekterzeugungen die Performance zerstört... tja, das wird man wohl einfach ausprobieren müssen  .
thD hat folgendes geschrieben : | Der GC ist immer an? Ich dachte nur unter den 2 Bedingungen:
-Wenn der Speicher so voll ist das, dass System nicht mehr kann.
-|| wenn die Anwendung keine Auslastung vorweist. |
"An" war im Sinne von "aktiv" gemeint, er ist eben niemals deaktiviert. Wenn Speicher knapp ist, wird eine teure Full Collection ausgelöst, ja. Die vielviel häufigeren, erstrebenswerteren Gen-0-Collections werden - grob gesagt - ausgelöst, nachdem eine bestimmte Anzahl von Objekten erstellt wurde, Punkt  .
Wenn du alles ein wenig genauer erfahren willst, dürfte hier dein Wissensdurst definitiv gestillt werden  : msdn.microsoft.com/e...gazine/bb985010.aspx
thD hat folgendes geschrieben : | Jetzt hätte ich noch zwei Fragen:
Edit: -Du arbeitest sicherlich als Programmierer, oder? Hast du vor nach dem Zivi als Programmierer zu arbeiten?
Edit: -Wenn ja, was hast du für eine Ausbildung gemacht? Hast du studiert? |
Die Fragen kamen jetzt unerwartet  . Ja, ich werde nach dem Zivi Informatik studieren. Weiteres aber vielleicht lieber per PN  .
_________________ >λ=
|
|
thD 
      
Beiträge: 33
Win 7, VirtualBox
C# (VS 2008)
|
Verfasst: Fr 18.12.09 22:11
Kha hat folgendes geschrieben : | | 100% managed Klassen brauchen nie einen Finalizer. Es gibt einfach nichts Sinnvolles, was er machen könnte, um den GC in irgendeiner Art zu unterstützen o.Ä. |
OK, soweit, so gut.
Kha hat folgendes geschrieben : | Alles, was unmanaged Ressourcen benutzt, also Code, der nicht auf der CLR läuft. Das sind meistens Funktionen der Windows-API oder sonstige DLL-Funktionen, die über P/Invoke importiert wurden.
Zum Beispiel ein GDI-Handle in Klassen wie Image: Der GC sieht beim Abräumen einer Instanz davon bloß ein Feld vom Typ IntPtr, kann aber unmöglich wissen, dass er darauf GdipDisposeImage aufrufen muss. Das muss der Entwickler ihm schon selbst sagen, nämlich über einen Finalizer.
Mit Handles ist das allerdings so eine Sache... wenn man nicht aufpasst, können die dem OS doch glatt ausgehen . Damit die Freigabe nicht erst geschieht, wenn der GC anspringt, sondern wenn der Benutzer der Klasse weiß, dass er das Objekt nicht mehr benötigt, gibt es das IDisposable-Pattern. Nachdem auf diesem Weg alle unmanaged Ressourcen freigegeben wurden, gibt es keinen Grund mehr, den teuren Finalizer vom GC aufrufen zu lassen - schon sind wir bei SuppressFinalize. |
Achso.
OK. Finalizer wenn der GC es frei gibt und Destruktor wenn man es explizit frei gibt.
Kha hat folgendes geschrieben : | | Gegenfrage: Was versprichst du dir davon? |
Also, falls man kreis.Dispose() ausversehen ein zweites mal aufruft.
Eigentlich wollte ich es nur probieren. Also wollte ich sagen wenn jemand kreis.Dispose() aufruft, der automatisch Kreis auf Null setzt. Somit, dachte ich, weis der GC das er das Objekt beim nächsten mal aufräumen löscht.
Kha hat folgendes geschrieben : | | Ohne weiteres gar nicht, wo bliebe da die tolle Entkuppelung der OOP? |
Was meinst du mit Entkuppelung?
Fallst du die Kapselung der OOP meinst, das bleibt ja gekapselt. Du kannst nur über kreis.Dispose() darauf zugreifen.
Kha hat folgendes geschrieben : | | Ein zweites Mal? Dispose ruft den Finalizer nicht selbst auf, ein direkter Aufruf ist in C# gar nicht möglich. |
Nein, aber der Finalizer ruft Dispose() auf. Und der Finalizer wird vom GC aufgerufen.
Und in Dispose() steht dann der Code vom Finalizer. Und dort steht dann GC.SuppressFinalize(this) der die Referenz übergibt wenn der Finalizer nicht mehr ausgeführt werden soll.
Oder habe ich da etwas falsch verstanden?
Kha hat folgendes geschrieben : | | Hm? Der Methode wird doch etwas übergeben? |
OK, weiß nicht was ich da gerade im Kopf hatte. Sry, blöde Frage.
Kha hat folgendes geschrieben : | XNA selbst ist objektorierentiert. Darauf, wie weit du im Rest des Projektes mit OOP gehst, hat das aber wenig Einfluss . Ob zu komplexes OO-Design mit zu vielen Objekterzeugungen die Performance zerstört... tja, das wird man wohl einfach ausprobieren müssen . |
OK. Wie weit kann man mit XNA gehen? Sind irgendwelche aktullen und grafisch aufwendigen Spiele damit bekannt? Oder ist XNA nur für Hobby-Programmierer?
Kha hat folgendes geschrieben : | "An" war im Sinne von "aktiv" gemeint, er ist eben niemals deaktiviert. Wenn Speicher knapp ist, wird eine teure Full Collection ausgelöst, ja. Die vielviel häufigeren, erstrebenswerteren Gen-0-Collections werden - grob gesagt - ausgelöst, nachdem eine bestimmte Anzahl von Objekten erstellt wurde, Punkt .
Wenn du alles ein wenig genauer erfahren willst, dürfte hier dein Wissensdurst definitiv gestillt werden : msdn.microsoft.com/e...gazine/bb985010.aspx |
OK. Thx.
mfG thD
|
|
Kha
      
Beiträge: 3803
Erhaltene Danke: 176
Arch Linux
Python, C, C++ (vim)
|
Verfasst: Sa 19.12.09 17:00
thD hat folgendes geschrieben : | | Also wollte ich sagen wenn jemand kreis.Dispose() aufruft, der automatisch Kreis auf Null setzt. Somit, dachte ich, weis der GC das er das Objekt beim nächsten mal aufräumen löscht. |
Ah. Aber selbst wenn es funktionieren würde: Was, wenn das nicht die einzige Referenz auf die Instanz war  ?
thD hat folgendes geschrieben : | Kha hat folgendes geschrieben : | | Ohne weiteres gar nicht, wo bliebe da die tolle Entkuppelung der OOP? |
Was meinst du mit Entkuppelung? |
Vor allem eine Vermeidung von Abhängigkeiten. Wenn der Aufgerufene den Aufrufer manipulieren könnte, hätten wir schon eine mehr.
thD hat folgendes geschrieben : | Kha hat folgendes geschrieben : | | Ein zweites Mal? Dispose ruft den Finalizer nicht selbst auf, ein direkter Aufruf ist in C# gar nicht möglich. |
Nein, aber der Finalizer ruft Dispose() auf. Und der Finalizer wird vom GC aufgerufen.
Und in Dispose() steht dann der Code vom Finalizer. Und dort steht dann GC.SuppressFinalize(this) der die Referenz übergibt wenn der Finalizer nicht mehr ausgeführt werden soll.
Oder habe ich da etwas falsch verstanden? | Könnte so stimmen, wenn du das Richtige meinst  . Im SuppressFinalize-Beispiel wird das standardmäßige Dispose(bool)-Pattern gezeigt.
thD hat folgendes geschrieben : | | Oder ist XNA nur für Hobby-Programmierer? |
Wahrscheinlich, höchstens kommerzielle Indie-Spiele wie dieses.
_________________ >λ=
|
|
thD 
      
Beiträge: 33
Win 7, VirtualBox
C# (VS 2008)
|
Verfasst: Sa 19.12.09 20:19
Kha hat folgendes geschrieben : | Ah. Aber selbst wenn es funktionieren würde: Was, wenn das nicht die einzige Referenz auf die Instanz war ? |
OK. Das wäre nicht besonders gut aber das muss doch der Programmierer wissen.
Kha hat folgendes geschrieben : | Könnte so stimmen, wenn du das Richtige meinst . Im SuppressFinalize-Beispiel wird das standardmäßige Dispose(bool)-Pattern gezeigt. |
Ja das habe ich richtig gemeint  .
Aha. Dann ist C# nicht für richtige Spiele geeignet. Ich dachte XNA wäre eine Alternative zu C++ und DirectX.
mfG thD
|
|
|