Autor Beitrag
thD
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 33

Win 7, VirtualBox
C# (VS 2008)
BeitragVerfasst: 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:
ausblenden volle Höhe C#-Quelltext
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
    {
        //Felder der Klasse Circle
        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;

        /// <summary>
        /// Konstruktor ohne Angaben.
        /// </summary>
        public Circle() {}
        
        /// <summary>
        /// Konstruktor mit Radius.
        /// </summary>
        /// <param name="radius">Kreisradius</param>
        public Circle(double radius)
        {
            this.Radius = radius;
        }
        
        /// <summary>
        /// Konstruktor mit Radius, X-Position und Y-Position der Kreismitte.
        /// </summary>
        /// <param name="radius">Kreisradius Integer</param>
        /// <param name="xPos">X-Position der Kreismitte</param>
        /// <param name="yPos">Y-Position der Kreismitte</param>
        public Circle(double radius, int xPos, int yPos)
        {
            this.Radius = radius;
            this.Xcoordinate = xPos;
            this.Ycoordinate = yPos;
        }

        /// <summary>
        /// Destruktor
        /// </summary>
        ~Circle()
        {
            Dispose();
        }

        /// <summary>
        /// Dispose-Methode
        /// </summary>
        public void Dispose()
        {
            GC.SuppressFinalize(this);
            ;
        }

        /// <summary>
        /// Radius-Methode mit Lese- und Schreibzugriff
        /// </summary>
        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!");
            }
        }

        /// <summary>
        /// Durchmesser-Methode mit Lesezugriff
        /// </summary>
        public double Durchmesser
        {
            get { return 2 * this.radius; }
        }

        /// <summary>
        /// Umfang-Methode mit Lesezugriff
        /// </summary>
        public double Umfang
        {
            get { return this.umfang; }
        }

        /// <summary>
        /// Area-Methode mit Lesezugriff
        /// </summary>
        public double Area
        {
            get { return this.area; }
        }

        /// <summary>
        /// XCoordinate-Methode mit Lese- und Schreibzugriff
        /// </summary>
        public int Xcoordinate
        {
            get { return this.Xcoordinate; }
            set { this.disposed = falsethis.xcoordinate = value; }
        }

        /// <summary>
        /// YCoordinate-Methode mit Lese- und Schreibzugriff
        /// </summary>
        public int Ycoordinate
        {
            get { return this.ycoordinate; }
            set { this.disposed = falsethis.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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Mi 16.12.09 23:14 
user profile iconthD hat folgendes geschrieben Zum zitierten Posting springen:
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?

user profile iconthD hat folgendes geschrieben Zum zitierten Posting springen:
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 ;) .

user profile iconthD hat folgendes geschrieben Zum zitierten Posting springen:
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 ;) .

user profile iconthD hat folgendes geschrieben Zum zitierten Posting springen:
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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 33

Win 7, VirtualBox
C# (VS 2008)
BeitragVerfasst: Do 17.12.09 00:10 
user profile iconKha hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconthD hat folgendes geschrieben Zum zitierten Posting springen:
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?


user profile iconKha hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconthD hat folgendes geschrieben Zum zitierten Posting springen:
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?


user profile iconKha hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconthD hat folgendes geschrieben Zum zitierten Posting springen:
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?


user profile iconKha hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconthD hat folgendes geschrieben Zum zitierten Posting springen:
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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Fr 18.12.09 01:13 
user profile iconthD hat folgendes geschrieben Zum zitierten Posting springen:
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.Ä.

user profile iconthD hat folgendes geschrieben Zum zitierten Posting springen:
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.

user profile iconthD hat folgendes geschrieben Zum zitierten Posting springen:
Dort steht allerdings nichts von Finalizer sondern Destruktor. Was ist der Unterschied?
Nur unterschiedliche Benennungen, siehe: en.wikipedia.org/wiki/Finalizer

user profile iconthD hat folgendes geschrieben Zum zitierten Posting springen:
Sollte man das so nicht machen?
Gegenfrage: Was versprichst du dir davon?

user profile iconthD hat folgendes geschrieben Zum zitierten Posting springen:
Und wie kann ich auf das aufrufende Objekt verweisen?
Ohne weiteres gar nicht, wo bliebe da die tolle Entkuppelung der OOP?

user profile iconthD hat folgendes geschrieben Zum zitierten Posting springen:
(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.

user profile iconthD hat folgendes geschrieben Zum zitierten Posting springen:
Wie übergibt der etwas?
Hm? Der Methode wird doch etwas übergeben?

user profile iconthD hat folgendes geschrieben Zum zitierten Posting springen:
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 :nixweiss: .

user profile iconthD hat folgendes geschrieben Zum zitierten Posting springen:
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 :D : msdn.microsoft.com/e...gazine/bb985010.aspx

user profile iconthD hat folgendes geschrieben Zum zitierten Posting springen:
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 :shock: . Ja, ich werde nach dem Zivi Informatik studieren. Weiteres aber vielleicht lieber per PN ;) .

_________________
>λ=
thD Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 33

Win 7, VirtualBox
C# (VS 2008)
BeitragVerfasst: Fr 18.12.09 22:11 
user profile iconKha hat folgendes geschrieben Zum zitierten Posting springen:
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.


user profile iconKha hat folgendes geschrieben Zum zitierten Posting springen:
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.


user profile iconKha hat folgendes geschrieben Zum zitierten Posting springen:
Nur unterschiedliche Benennungen, siehe: en.wikipedia.org/wiki/Finalizer

OK. Finalizer wenn der GC es frei gibt und Destruktor wenn man es explizit frei gibt.


user profile iconKha hat folgendes geschrieben Zum zitierten Posting springen:
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.


user profile iconKha hat folgendes geschrieben Zum zitierten Posting springen:
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.


user profile iconKha hat folgendes geschrieben Zum zitierten Posting springen:
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?


user profile iconKha hat folgendes geschrieben Zum zitierten Posting springen:
Hm? Der Methode wird doch etwas übergeben?

OK, weiß nicht was ich da gerade im Kopf hatte. Sry, blöde Frage.

user profile iconKha hat folgendes geschrieben Zum zitierten Posting springen:
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 :nixweiss: .

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?


user profile iconKha hat folgendes geschrieben Zum zitierten Posting springen:
"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 :D : msdn.microsoft.com/e...gazine/bb985010.aspx


OK. Thx.


mfG thD
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Sa 19.12.09 17:00 
user profile iconthD hat folgendes geschrieben Zum zitierten Posting springen:
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 :zwinker: ?

user profile iconthD hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconKha hat folgendes geschrieben Zum zitierten Posting springen:
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.

user profile iconthD hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconKha hat folgendes geschrieben Zum zitierten Posting springen:
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.

user profile iconthD hat folgendes geschrieben Zum zitierten Posting springen:
Oder ist XNA nur für Hobby-Programmierer?
Wahrscheinlich, höchstens kommerzielle Indie-Spiele wie dieses.

_________________
>λ=
thD Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 33

Win 7, VirtualBox
C# (VS 2008)
BeitragVerfasst: Sa 19.12.09 20:19 
user profile iconKha hat folgendes geschrieben Zum zitierten Posting springen:
Ah. Aber selbst wenn es funktionieren würde: Was, wenn das nicht die einzige Referenz auf die Instanz war :zwinker: ?

OK. Das wäre nicht besonders gut aber das muss doch der Programmierer wissen.


user profile iconKha hat folgendes geschrieben Zum zitierten Posting springen:
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 ;).


user profile iconKha hat folgendes geschrieben Zum zitierten Posting springen:
Wahrscheinlich, höchstens kommerzielle Indie-Spiele wie [url=www.xbox.com/de-DE/g...rcade/]dieses[/url].

Aha. Dann ist C# nicht für richtige Spiele geeignet. Ich dachte XNA wäre eine Alternative zu C++ und DirectX.


mfG thD