Forum: PC-Programmierung Globale Variable ersetzen [C#]


von AnonymousSquirrel (Gast)


Lesenswert?

Hallo,

spiele zum Spaß ein bisschen mit C# und möchte in einem Timerevent bei 
jedem Durchlauf eine Variable um 1 inkrementieren. Allerdings scheitere 
ich bisher daran (normal unter C würde ich wohl eine globale Variable 
nutzen).

Habe es dann mit Hilfe einer Klasse versucht:

 class plotter
        {
            public int xval;

            public plotter()
            {
                xval = 0;
            }

            public void ink_datenpunkt()
            {
                xval++;
            }
        }

Nach meinen bisherigen Erfahrungen scheint das auch zu funktionieren. 
Nur das Problem hat sich nicht verändert, die Variable wird ja dennoch 
jedes Mal zurückgesetzt. Und extern kann ich ja auf die Variable nicht 
zugreifen, oder?

Stehe noch ganz am Anfang von Objektorientierung usw. Irgendwann muss 
man ja einmal damit starten.

Gruß
Squirrel

von Karl heinz B. (kbucheg)


Lesenswert?

> die Variable wird ja dennoch jedes Mal zurückgesetzt

Nur dann wenn du jedesmal ein neues plotter Objekt
erzeugst. Ansonsten behält plotter.xval seinen Wert
bei. Das heist also, du musst untersuchen, warum du
jedesmal ein neues Objekt erzeugst und nicht das
vorhandene weiterbenutzt.

Allerdings kannst du auch sowas machen: Eine Variable
die sich alle plotter-Objekte teilen, die also zwar
zur Klasse gehört aber nicht zu einem bestimmten plotter
Objekt, sondern allen plotter Objekten gemeinsam:

class plotter
        {
            public static int xval;

(Wieso eigentlich public? Das ist eines der ersten Dinge,
die man sich bei OOP abgewöhnen sollte.)

von AnonymousSquirrel (Gast)


Lesenswert?

Ich erzeuge zwangsweise bei jedem Timer-Tick ein neues Objekt, und zwar 
weil ich nicht drauf komme, wie es anders zu lösen ist. Habe versucht 
das Objekt extern zu erzeugen (z.B. mit Klick auf einen Button), nur 
dann sagt Visual Studio mir, dass es im Kontext Timerevent nicht 
existiert. Wie erstelle ich ein Objekt, dass überall existiert? Drehe 
mich also bisher im Kreis ..

>>Wieso eigentlich public?

Kann ich auch ohne das public von außen auf die Variable zugreifen? Habe 
das nicht mal richtig begriffen, und dann paranoid wie ich bin, 
(testweise) verwendet.

Gruß
Squirrel

von Karl H. (kbuchegg)


Lesenswert?

> Ich erzeuge zwangsweise bei jedem Timer-Tick ein neues Objekt,
> und zwar weil ich nicht drauf komme, wie es anders zu lösen ist.

Der Timer-Tick landet ja in einem Objekt (deiner Form).
Wenn du also der Form ein plotter Objekt verpasst, dann
ist das natürlich auch im Handler des Timer Ticks verfügbar.
Die Handler Funktion ist Teil des Form Objektes, das plotter
Objekt ist Teil der Form. Funktionen einer Klasse können
auf alle Objekte in dieser Klasse zugreifen.

Stell es dir einfach so vor:
Dein Form besteht aus
  * Einer Menge Graphik
  * Einem Konstruktor
  * einem Timer
  * einem plotter Objekt

von Karl H. (kbuchegg)


Lesenswert?

> Kann ich auch ohne das public von außen auf die Variable zugreifen?

Der springende Punkt ist genau dieser:
Niemand soll von aussen auf eine Member Variable zugreifen können!

Wenn jemand etwas von einem Objekt will, dann soll er gefälligst
eine der public Funktionen dafür benutzen! Aber er soll sich
auf keinen Fall direkt an den Variablen vergreifen können.

Der Sinn dahinter ist: Wenn eine Veränderung eines Wertes
über eine Funktion der Klasse geführt wird, dann kann diese
Funktion sicherstellen, dass da kein Unsinn eingestellt wird.
Erlaube ich aber einen Zugriff direkt auf die Variablen, dann
kann jeder der will, irgendwelchen Blödsinn in meine Objektvariablen
schreiben. Das widerspricht aber komplett einer zentralen
Philosophie im OOP: jedes Objekt ist für sich selbst dafür
verantwortlich, dass es in einem konsistenten und gültigen
Zustand bleibt.

Beispiel: Wenn ich eine Datumsklasse habe, und ich gebe
Tag, Monat, Jahr nach aussen hin frei, dann kann ich nicht
verhindern, dass irgendein Nachwuchsprogrammierer den 45. 14. 2006
einstellt. Gebe ich aber die Variablen nicht frei, sondern biete
ihm stattdessen eine Funktion an

    public void Set( int d, int m, int y )
    {
      ...
    }

dann kann ich in dieser Setzfunktion prüfen, ob denn dieses
Datum überhaupt gültig ist. Wenn nicht, dann schmeiss ich
dem Aufrufer eine gesalzene Exception um die Ohren.

von AnonymousSquirrel (Gast)


Lesenswert?

Hallo Karl Heinz,

ok, habs verstanden und erlaube keinen direkten Zugriff mehr auf die 
Variablen eines Objekts. Ich sehe schon, OOP erfordert von der ersten 
Zeile an Disziplin : )

D.h. das Objekt Plotter muss im Form1 instanziert werden -> funktioniert 
!
Bei weiteren Fragen im Laufe meines C# Lernprozesses würde ich ggf. hier 
nochmal posten.

Vielen Dank u. Gruß
Squirrel

von Karl H. (kbuchegg)


Lesenswert?

> Ich sehe schon, OOP erfordert von der ersten
> Zeile an Disziplin : )

Auch nicht mehr als in C. Eher weniger.

Vergleich mal, In C haettest du geschrieben:

struct Date {
  int Day;
  int Month;
  int Year;
};

und dazu noch eine Setzfunktion

void SetDate( struct Date* date, int d, int m, int y )
{
  .... Mambo zambo um in date->Day, date->Month und
  .... date->Year zu setzen, inkl Prüfung auf Gültigkeit
}

Jemand der dieses benutzt, kann jetzt machen

int main()
{
  struct Date Birthday;

  SetDate( &Birthday, 24, 12, 2006 );
}

Er kann, er muss aber nicht! Er könnte genau so gut machen:

int main()
{
  struct Date Birthday;

  Birthday.Day = 45;
  Birthday.Month = 14;
  Birthday.Year = 2006;
}

und nichts und niemand könnte ihn daran hindern.

Dadurch dass in OOP die Funktion SetDate() quasi in die
struct hineinverschoben wird, also ein integraler Bestandteil
der struct wird (und das Ganze dann Klasse genannt wird)
eröffnet sich erst der Objekt-Ansatz. Bei einer C-struct
würde es keinen Sinn machen, gewisse Zugriffe von aussen
zu verbieten, den alle Zugriffe auf Internals müssen
zwangsweise von aussen erfolgen. Erst dadurch, dass ich
Funktionen in die struct aufnehmen kann, wird der Weg frei
um Zugriffsbeschränkungen zu implementieren.

In einem gewissen Sinne braucht es natürlich bei der
Implementierung einer Klasse mehr Disziplin. Auf der
anderen Seite befreie ich aber den Verwender der Klasse
davon, Disziplin zu halten! Er hat gar keine andere Möglichkeit
mehr: Das Einzige was er benutzen kann, ist die Setz-Funktion
und ich erspare (na ja) ihm die Qual der Wahl ob er jetzt
direkt auf die Member-variablen zugreift oder den offiziell
erlaubten Weg geht. Dadurch habe ich als Implementierer einer
Klasse aber wesentlich größere Kontrolle darüber, wie eine
Datenstruktur benutzt wird, bzw. ich kann vorschreiben wie
sie benutzt werden soll und bin nicht mehr auf Gedeih und
Verderben dem Fair-Play des Verwenders ausgeliefert.


von student29 (Gast)


Lesenswert?

Hallo, habe fast das selbe Problem und komme damit nicht zu recht.
Bin ein Neuling..
Folgendes zu meinem Problem.
Ich starte in Visual Studio einen Timer und möchte den Wert diesen 
Timers mit einem globalen Timer abgreifen und an Methoden weitergeben.
Habt ihr eventuell ein paar Ansätze hierfür an denen ich anknüpfen 
könnte?
Vielen Dank!

von Borislav B. (boris_b)


Lesenswert?

student29 schrieb:
> Ich starte in Visual Studio einen Timer und möchte den Wert diesen
> Timers mit einem globalen Timer abgreifen und an Methoden weitergeben.

Das klingt reichlich wirr :-)

1) Was für einen Timer benutzt du? Da gibt es diverse Möglichkeiten...
2) Wo/wie ist der Timer deklariert? Wie instanziierst du ihn?
3) Was meinst du mit "globaler" Timer?
4) Hast du tatsächlich zwei Timer? Wenn ja warum?
5) Was meinst du mit "einen Timer mit einem anderen Timer abgreifen"?
6) Was hast du überhaupt vor?
7) Allgemein: was für Frameworks benutzt du, was für ein Anwendungstyp 
ist das? (.NET, Mono, Console, WinForms, WPF...)

Dann kann Dir ggf. geholfen werden...

von student29 (Gast)


Lesenswert?

=)

Also ich benutze Visual Studio WinForms.

Ich habe einen timer aus dem Werkzeugkasten gewählt der jede sekunde 
tickt.
d.h. mein timer startet bei o und zählt immer +1 hoch.
0sec
1 sec
2sec
usw. ...

mein Ziel ist es anhand dieses timers zu bestimmten Zeitpunkten 
Bestimmte Methoden auszuführen.

ZB habe ich einen array mit 4 variablen.

[a1,a2,a3,a4]
a1 ist mein Startwert zb. a1=4 d.h. methode das erste mal bei timer wert 
4 ausführen.
a2 mein Zyklus Wert(d.h. zb. a2=2 bei jedem 2.tick ausführen)
a3 ist eine Variable für die Haufigkeit (wie oft führe ich diese Methode 
aus. zb a=3 bei jedem 2.takt mehtode ausführen und das ganze dann 3mal.
Danach wird diese Methode nicht mehr ausgeführt.
a4 sind die daten die ich dann z.b. am ende der Methode an die Console 
sende.

Ist das Verständlich?

Vielen Dank für die Antwort

von Borislav B. (boris_b)


Lesenswert?

OK, es wird klarer :-)

Aber was ist jetzt genau dein Problem?
Warum machst du das nicht einfach so, wie du geschrieben hast?

: Bearbeitet durch User
von student29 (Gast)


Lesenswert?

ich bekomme es nicht hin den wert des timers an die methoden 
weiterzugeben.

von Borislav B. (boris_b)


Lesenswert?

Etwa so?
1
void OnTime(...)
2
{
3
 mCounter++;
4
5
 if(mCounter % 3 == 0) // oder so...
6
 {
7
  Methode1(mCounter);
8
  Methode2(mCounter);
9
 }
10
}

von student29 (Gast)


Lesenswert?

Danke für die Bemühungen aber ich bin zuzeit echt am verzweifeln.
Ich starte einen Counter.

 myTimer.Tick += new EventHandler(TimerEventProcessor); //mit jedem tick 
neu Eventhandler -> ruft timereventmethode auf
            myTimer.Interval = 1000; 
//Timer Intervall
            myTimer.Start(); 
//Timer starten


            while (GlobVar.exit == 0) 
//solange GlobVar 0 ausführung der Events
            {
                Application.DoEvents();

            }



private static void TimerEventProcessor(Object myObject, EventArgs 
myEventArgs) // wird von Main ausgeführt solange exit GlobVar = 0
        {
            alarmCounter += 1; //Timer++
            GlobVar.t = alarmCounter;

            {
                if (GlobVar.t == GlobVar.a)     //wenn timerwert 
variable a entspricht zyklus 1 aufrufen
                {
                    Zyklus1();
                }
            }
        }

                  static void Zyklus1()        // MethodeZyklus1
        {



                        Console.WriteLine("Jetzt");



Ich muss bei jedem tick des timer jetzt gezielt eine nachrichten senden 
und nach z.b 10 ticks des timers sagen können ok jetzt nicht mehr.
Ich bekomme es einfach nicht hin getacktet nachrichten auszugeben oder 
zu senden. BITTE HILFT MIR?

von Borislav B. (boris_b)


Lesenswert?

student29 schrieb:
> Ich bekomme es einfach nicht hin getacktet nachrichten auszugeben oder
> zu senden. BITTE HILFT MIR?

Was ist denn jetzt GENAU das Problem?
Ich verstehe ehrlich gesagt nicht so ganz, woran es scheitert...

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.