HOME www.Junoland.de (c) Copyright 2008 °Andreas Klotz, Cologne, Germany [upd.Oct.2008] AKL@Junoland.de
Nr | Autor | Titel | Seiten | EUR | Verlag | Jahr | ISBN |
---|---|---|---|---|---|---|---|
D01 | Louis / Strasser | C# in 21 Tagen | 844 | 44,95 | Markt + Technik | 2002 | 3-8272-6069-8 |
D02 | Armin Hanisch | Go To C# | 534 | 39,95 | Addison Wesley | 2002 | 3-8273-1932-3 |
D03 | Jürgen Bayer | C# Nitty Gritty | 448 | 12,95 | Addison Wesley | 2002 | 3-8273-1856-4 |
D04 | Frank Eller | C# Lernen | 322 | 24,95? | Addison Wesley | 2001 | 3-8273-1784-3 |
D05 | Moses / Nowak | C# Progammieren unter .Net | 645 | 49,95 | Franzis' | 2002 | 3-7723-7224-4 |
D06 | Andrew Troelsen | C# und die .Net-Plattform | 928 | 50,00 | mitp | 2002 | 3-8266-0833-X |
D07 | Golo Haas | Guide To C Sharp | . | . | www.guidetocsharp.de | 2002 | . |
D08 | Erler / Ricken | C# - Das Einsteigerseminar | 425 | ? | moderne industrie Buch | 2001 | 3-8266-7169-4 |
D09 | Eric Gunnerson | C Sharp - Die neue Sprache | . | . | www.galileocomputing.de | 2001 | . |
D10 | Helma Spona | C# Der leichte Einstieg | 384 | 9,95 | Markt + Technik | 2002 | 3-8272-6399-9 |
Inzwischen (6 Jahre später) ist mein Favorit das Buch, das bei Galileo online zu lesen und auch komplett zum kostenlosen Download bereitsteht:
Visual C# 2008 von Andreas Kuehnel
Ich denke, dass der Autor meinem Ideal eines guten Fachbuch-Schreibers am nächsten kommt.
[Gute Schreibe]
Und das sage ich nicht etwa, weil es das Buch für 'umme' gibt!
Ich komme bei meiner Suche nach C#-Funktionen immer wieder über Google auf dieses Buch zurück und finde dort meistens auch immer die besten deutschsprachigen Erklärungen.
"Felder sind die Datenelemente der Klasse. Definiert werden sie durch Angabe eines Zugriffsspezifizierers, des Datentyps und des Feldnamens.
Ihr Gültigkeitsbereich ist die Klasse selbst, d.h. alle Methoden der Klasse (einschließlich Konstruktor, Destruktor, Eigenschaften) können auf die Felder zugreifen.
Bei der Instanzbildung bekommt das erzeugte Objekt von jedem Feld der Klasse eine eigene Kopie. Die Lebensdauer eines Felds ist daher gleich der Lebensdauer des Objekts, zu dem es gehört."
Der übliche Ort zur Initialisierung von Feldern ist der Konstruktor:"
class CDemo { int feld1; internal CDemo() { feld1 = 12; } ...
"Allerdings handelt es sich hierbei technisch gesehen gar nicht um eine Initialisierung, son- dern lediglich um die Zuweisung eines Anfangswerts. Initialisiert wurde das Feld nämlich bereits bei seiner Erzeugung (als es im Speicherbereich des Objekts angelegt wurde). Der Compiler weist den Feldern dabei ihren Standardwert zu (beispielsweise O für 1 nt oder double, false für bool). Wenn Sie möchten, dass ein Feld mit einem anderen Wert initiali- siert wird, müssen Sie diesen bei der Felddefinition angeben:"
class CDemo { int feld1 = 122; internal CDemo() { Console.WriteLine(feld1); } ...
"Die echte Initialisierung ist schneller als die Zuweisung eines Anfangswerts im Konstruk- tor, aber auch weniger flexibel, da im Wesentlichen nur Literale zugewiesen werden kön- nen."Literale? Also manuell eingetippt und nicht übernommen von einer anderen Variablen.
"Statische Felder sind Felder, die mit dem Schlüsselwort static deklariert wurden. Statische Felder existieren lediglich als Felder ihrer Klasse. Nicht-statische Felder werden bei der Objekterzeugung kopiert, damit jedes erzeugte Objekt eine eigene Kopie des Feldes erhält. Von einem statischen Feld einer Klasse gibt es allerdings nur eine einzige Kopie. Statische Felder stellen daher eine Möglichkeit dar, mit der die einzelnen Objekte einer Klasse untereinander Daten und Informationen austauschen können."Endlich mal ein Autorengespann, das an mehr als das bloße Gezählt-werden denkt!
"Statische Felder werden immer über den Namen der Klasse angesprochen. Statische Fel- der können daher benutzt werden, ohne dass ein Objekt der Klasse erzeugt wurde:"...Nicht 'können' - 'müssen' ist richtig!
"Schließlich sind statische Felder die einzigen Felder, auf die statische Methoden zugreifen können."...
"Statische Felder sind beileibe nicht nur für die Implementierung von Klassen interessant, die reine Sammlungen statischer Methoden darstellen. Auch das Mischen statischer und nicht-statischer Klassenelemente ist möglich. Das folgende Beispiel nutzt ein statisches Feld, um mitzuzählen, wie viele Objekte der Klasse erzeugt wurden:"...
"Felder sind letztlich nichts anderes als Variablen, die im Gültigkeitsbereich einer Klasse definiert wurden. Insgesamt haben Sie nun also vier verschiedene Kategorien von Variab- len kennen gelernt.Eine sehr schöne Aufstellung, danke, ihr sprecht meine Sprache!
# lokale Variable : Variable, die innerhalb einer Methode deklariert wird
# Instanzvariable : nicht-statisches Feld, von dem jedes erzeugte Objekt (Instanz) der Klasse eine eigene Kopie erhält
# Klassenvariable : statisches Feld, von dem es stets nur eine Kopie gibt
# Objektvariable : eine Variable, die eine Referenz auf ein Klassenobjekt im Speicher enthält"
"Statische Methoden werden ebenso wie die statischen Felder durch Voranstellung des Schlüsselwortes static definiert und nur über den Klassennamen aufgerufen.Naja, wie soll das denn auch gehen? Auf welches Objekt soll die static Methode denn dann bezogen werden, frage ich mich. Und deshlab gibt es eben auch kein 'this' für diese Methoden; bitte so herum und nicht anders, oder bin ich hier derjenige, der die Dinge zu verwirrt sieht?
Statische Methoden können nur auf statische Felder einer Klasse zugreifen. Nach den Ausführungen des vorangehenden Abschnittes sollte auch klar sein, warum. Statische Methoden verfügen über keinen this-Verweis."
Statische Methoden und private KonstruktorenNa gut, wird also nur einmalig vor Gebrauch der Klasse initialisiert. Hätte man vielleicht auch ausdrücklicher sagen sollen, finde ich.
"Statische Methoden werden meist zur Implementierung von Funktionensammlungen ver- wendet. Es ist aber auch möglich, in einer Klasse, die echte Objekte beschreibt, normale und statische Methoden gemeinsam zu verwenden.
Schauen Sie sich noch einmal das Programm StatischeFelder.cs aus Abschnitt »Statische Felder« an. Dort wurde ein statisches Feld zum Zählen der Gespenster-Objekte verwendet. Das Beispiel hatte aber keine sinnvolle Verwendung für den Zähler. In dem nachfolgen- den Beispiel soll der Zähler dazu genutzt werden, die maximale Anzahl Gespenster auf 3 zu begrenzen. Dies wird mit Hilfe eines Tricks erreicht, der darin besteht, den einzigen Konstruktor der Klasse als private zu deklarieren und die Objekterzeugung durch eine sta- tische Methode zu kontrollieren."
"Sollen die Anweisungen einer while-Schleife beim ersten Aufruf ausgeführt werden, muss die Bedingung beim ersten Aufruf der while-Schleife erfüllt sein. Ist das nicht der Fall, wird der komplette Anweisungsblock der while-Schleife ignoriert. Sollte aber eine Schleife, die mit dem Schlüsselwort while ausgeführt werden soll, mindestens einmal durchlaufen wer- den, benötigen wir eine do-while-Schleife. Diese Art der Schleife bezeichnet man auch als fußgesteuerte Schleife, da die Bedingung erst am Ende des Anweisungsblocks der while- Schleife überprüft wird.
Die Syntax einer do-while-Schleife sieht folgendermaßen aus:do Anweisung; while(Ausdruck);oder:do { Anweisung(en); } while(Ausdruck);Die Syntax der do-while-Schleife verdeutlicht den Ablauf der überprüfung. Bevor der Aus- druck überprüft wird, werden die Anweisungen ausgeführt. Auffallend ist auch das Semiko- lon im Schleifenfuß. Dieses Semikolon darf unter keine Umständen fehlen, da sonst der Compiler eine Fehlermeldung erzeugt. Programmtechnisch stellt der Schleifenfuß eine Leeranweisung dar, die mit dem Schlüsselwort do verknüpft ist.using System; class CDoWhile { static void Main(string[] args) { int iRef = 5; while (iRef != 5) Console.WriteLine("(while) Wert iRef: {0}" ,iRef): do Console.WriteLine("(do-while) Wert iRef: {0}" ,iRef): while (iRef != 5); Console.ReadLine(); } }In der Zeile 9 wird eine Variable iRef vom Typ Integer deklariert und mit dem Wert 5 initialisiert. Die Zeile 11 verwendet die while-Schleife, um den Wert in der Konsole auszugeben. Dazu kommt es aber nicht, da es sich um eine kopfge- steuerte Schleife handelt und die Bedingung des Ausdrucks der while-Schleite nicht erfüllt wird. Ist es aber erwünscht, die Anweisungen, die im Anweisungs- block einer while-Schleife stehen, mindestens einmal zu durchlauten, muss man auf eine do-while-Schleife ausweichen. Die Ausgabe in Zeile 15 wird aus- geführt, bevor die while-Schleite die Bedingung ihres Ausdrucks überprüft."
"Jede Instanz einer Klasse besitzt ebenfall ihre eigene Instanz der Mit- glieder dieser Klasse. Dazu ein Beispiel: Im letzten Abschnitt habe ich Ihnen die Klasse Konto vorgestellt. Wird mit new aus dieser Klasse eine Instanz erzeugt, besitzt jede Instanz eine eigene Kopie des Feldes fsaldo. Schließlich hätten Sie etwas dagegen, dass eine Buchung auf ein Konto alle anderen Instanzen Ihrer Geschäftskonten auf den gleichen Wert setzt, es sei denn, Sie haben gerade ein völlg revolutionäres Buchhaltungskonzept erfunden ... "Mitglieder? Sind damit nicht-statische Elemente einer Klasse gemeint, wie zB Objekt-Variablen? Ist zwar mit gutem Willen noch gerade zu vetehen, könnte man aber leichter fasslich gestalten, etwa so:
"Bei bestimmten Gelegenheiten macht es aber keinen Sinn, wenn Daten oder Code für jede Instanz einer Klasse gesondert angelegt werden. Bei unserer Konto-Klasse könnte die Notwendigkeit einer Euro-Umrech- nung auftreten, daher solle ich wohl besser irgendwo in der Klasse die offiziellen Umrechnungskurse für die einzelnen Währungen in der Klasse unterbringen. Die Werte sind aber nun wirklich für jede Instanz der Klasse gleich und müssen daher eigentlich nur einmal gespeichert werden. Diese Daten gehören logisch gesehen also eher zur gesamten Klasse als zu einer bestimmten Instanz."Okay, das treffende Beispiel versöhnt mich wieder.
"Solche Mitglieder einer Klasse werden als statische Mitglieder (static members) bezeichnet. Einige andere Programmiersprachen bezeichnen solche Konstruktionen auch als Klassenfunktionen (classfunctions), was sprachlich beinahe besser passt. Ein weiteres Beispiel ist der Startpunkt jeder .NET-Anwendung in C#:...
public static void Main() { }
Auch dieser Code muss nur einmal im Speicher vorhanden sein, unab- hängig davon, wie viele Instanzen der Klasse ich erzeuge. Wie Sie erkennen, wird bei der Deklaration eines static einfach dieses Schlüs- selwort nach der Sichtbarkeit und vor dem Datentyp angegeben. "
"Wenn ein static zur Klasse und nicht zu einer Instanz (einem Objekt) gehört, dann kann auf dieses Feld oder diese Methode auch nur über die Klasse zugegriffen werden."Ja, aber auf normale Objekt-Eigenschaften greift man doch - zumindest indirekt - ebenfalls letzten Endes über die Klassen-Bezeichnung zu! Indem man nämlich bei der Initialisierung der Objekte mit new sagt, von welcher Sorte, sprich von welcher Klasse, das Objekt sein soll. Besser wäre es also zu sagen: ' ... auf dieses Feld oder diese Methode nur über die Nennung des Klassennamens direkt zugegriffen werden - also ohne Nennung eines Objekts dieser Klasse'.
"Sie können für eine Klasse auch einen statischen Konstruktor definie- ren. Dieser kann beispielsweise zur Berechnung von statischen Feldern dienen, welche als readonly deklariert sind, weil der Wert zur Zeit der Kompilierung noch nicht feststand.
class Machwas { public Machwas() { // der normale konstruktor } // keine modifikatoren zulassig static Machwas() { // der statische konstruktor } }
"Nachdem statische Konstruktoren zur Klasse gehören, sind bei ihnen Modifikatoren für die Sichtbarkeit nicht zulässig. Die Benutzung von statischen Konstruktoren bietet sich für einmalige Initialisierungen an, die für die gesamte Klasse und nicht für einzelne Instanzen dieser Klasse durchgeführt werden sollen."Gut, dass der Autor diese einleuchtende Möglichkeit erwähnt. Habe ich noch nicht all zu oft in anderen Büchern zum Thema vorgefunden.
"Die .NET-Laufzeitumgebung garantiert, dass ein statischer Konstruktor nach dem Start der Anwendung und vor der Erstellung der Instanz die- ser Klasse ausgeführt wird, aber nicht mehr. Der Aufruf kann zeitlich also von der tatsächlichen Erstellung einer Instanz dieser Klasse deutlich getrennt sein."Aha, so kann man sich das Ganze also auch noch 'aus Compiler-Sicht' vorstellen, warum nicht. Aber kann es nicht sein, dass der Aufruf nicht unbestimmt irgendwann zwischen A und B stattfindt, sondern ganz genau vor dem ersten Aufruf eines Elements von B? Dies sind Kleinigkeiten, könnte sein, dass ich mich irre.
Bedingte Schleifen - DO & WHILE
"Wenn Sie in C# eine Anweisung oder einen Block mehrmals wieder- holt ausführen lassen möchten, haben Sie zwei Möglichkeiten, abhän- gig davon, ob Sie bereits wissen, wie oft diese Wiederholung gesche- hen soll. Fall ja, verwenden Sie die for-Schleife, fall nicht, dann benutzen Sie entweder do oder while.
while arbeitet so, wie Sie das wahrscheinlich auch von anderen Spra- chen her kennen: ein Ausdruck wird zu einem bool-Wert evaluiert und falls dieser true ergibt, wird die Anweisung (eine einzelne Anweisung oder ein Block) ausgeführt. Anschließend wiederholt sich das Ganze, bis die Auswertung des Ausdrucks den Wert false ergibt.string s; while ( (s = Console.ReadLine() != null ) // ausgeben, bis alle Zellen gelesen wurden Console.WriteLine(s);Lesern aus der C- und Java-Ecke wird dieser Code wahrscheinlich nur ein Gähnen entlocken, für VB-Umsteiger möchte ich an dieser Stelle doch noch einmal den Ausdruck hinter while erläutern, da dieses Kon- zept in C-ähnlichen Sprachen üblich ist.
Nach while steht ein Ausdruck, der einen bool-Wert ergeben muss. Die Zuweisung von s = Console.ReadLine() liefert entweder den String aus der Eingabe oder null, falls keine Zeilen mehr zur Verfü- gung stehen (da das Ende der Datei erreicht ist). Dieses Ergebnis wird mit dem Literal null verglichen und liefert damit einen bool-Wert. Sormt haben Sie eine Zuweisung und einen Vergleich in einem Aus- druck erreicht. Diese Art der Codierung werden Sie in C#-Code noch häufig sehen.
do-Schleifen funktionieren ähnlich, arbeiten allerdings als so genannte annehmende Schleifen, d. h. zuerst wird der Schleifenkörper einmal aus- geführt, dann wird die Bedingung getestet. Diese Art der Wiederho- lung eignet sich vor allem dann, wenn Sie eine Aktion ausführen möchten, welche selbst erst die Bedingung testbar macht. Ein Beispiel dafür sind kommandogesteuerte Programme (wie ein ftp-Client), bei denen Sie das Kommando erst dann kennen, wenn es vom Benutzer eingegeben wurde. Sie benötigen also mindestens eine Eingabe, an der Sie die Bedingung testen können.string s; do { s = Console.ReadLine(); // ausgeben, bis QUIT gelesen wurde Console.WriteLine(s); } while (s != "QUIT" );"
"Normale Eigenschaften und Methoden sind immer einer Instanz ei- ner Klasse zugeordnet.Manchmal besteht aber auch der Bedarf, dass eine Eigenschaft nur ein einziges Mal für alle Instanzen dieser Klasse gespeichert ist oder dass eine Eigenschaft oder Methode ohne Instanz der Klasse verwendet werden kann."Okay, ist kurz und klar.
"Eine statische Eigenschaft ist nur einmal für die Klasse und nicht für jedes Objekt separat gespeichert.Damit können Sie Werte zwischen den einzelnen Instanzen der Klasse austauschen oder die globalen Variablen der strukturierten Programmierung simulieren."Okay, noch einmal anders zur Verdeutlichung.
"In einer Kontoverwaltung ist z.B.der Kontostand jedem Kontoobjekt separat zugeordnet,der Zinssatz sollte aber für alle Kontoobjekte ge- meinsam gespeichert sein.Diese Eigenschaft sollte statisch sein und wird einfach mit dem Modifizierer static deklariert: "...
"Alle Methoden (normale und statische) des Objekts können auf stati- sche Eigenschaften zugreifen.Die ZinsenRechnen-Methode des Bei- spiels demonstriert dies.Eine statische Eigenschaft kann auch ohne Instanz einer Klasse gesetzt und geschrieben werden. Geben Sie dazu den Klassennamen als Präfix an " ...Tja, 'kann auch ohne' ? Wieso 'kann auch' ? Das hört sich irgendwie so an, als wenn es auch mal 'mit' geht, so wie man seinen Kaffee mit oder ohne Milch nehmen kann. Ob da nun eine Instanz ode mehrer existieren oder gar keine - eine static-Eigenschaft steht gänzlich unabhängig von etwaigen Instanzen! (Auch wenn man in ihr Informationen sammeln könnte, die mit diesen Instanzen inhaltlich zusammenhängen).
"In manchen Fällen ist es sinnvoll oder notwendig,Daten so zu verwal- ten,dass diese global im gesamten Programm gelten.Eigentlich sollten solche Daten grundsätzlich (und besonders bei der OOP ver- mieden werden).Globale Daten beinhalten viele potenzielle Fehler- quellen,da jeder Programmteil auf diese Daten zugreifen und diese (eventuell fehlerhaft) verändern kann. Außerdem machen globale Daten ein Programm sehr undurchsichtig. Wenn Sie das Risiko aber eingehen wollen oder müssen, verwenden Sie dazu einfach eine Klasse mit lediglich statischen Eigenschaften:"...
"Statische Methoden können - wie statische Eigenschaften - ebenfalls ohne Instanz der Klasse verwendet werden. Diese Methoden verwenden Sie (sehr selten) für Operationen, die sich auf die Klasse und nicht auf einzelne Objekte beziehen"- wirklich so selten?! - weiter:
"über statische Methoden können Sie beispielsweise die statischen (privaten) Eigenschaften einer Klasse bearbeiten. Ein Beispiel dafür fehlt hier, weil diese Technik doch eher selten eingesetzt wird."Wieso selten? Verstehe ich nicht! Kommt doch viel öfter mal vor, als die reine Lehre der OOP es vorschreibt, oder?
"Wesentlich häufiger werden statische Methoden eingesetzt,um glo- bale, allgemein anwendbare,Funktionen in das Projekt einzufügen. Das .NET-Framework nutzt solche Methoden sehr häufig.Die Klasse Math besteht z.B.fast ausschließlich aus statischen Methoden. Wenn Sie z.B.in Ihren Projekten häufig verschiedene Maße und Ge- wichte in nationale Einheiten umrechnen müssen, können Sie dazu eine Klasse mit statischen Methoden verwenden"...
"Die Verwendung statischer Methoden für allgemeine Aufgaben ist wesentlich einfacher,als wenn Sie dazu immer wieder Objekte in- stanzieren müssten.Um eine Methode der Klasse UnitConversion zu verwenden,müssen Sie lediglich den Klassenamen angeben" ...Ja, ist breit und gut ausgewalzt.
"Neben Eigenschaften und Methoden können auch Konstruktoren sta- tisch deklariert werden. Ein statischer Konstruktor wird nur ein einzi- ges Mal aufgerufen, nämlich dann, wenn die erste Instanz der Klasse erzeugt wird. Damit können Sie Initialisierungen vornehmen,die für alle Instanzen der Klasse gelten sollen. Deklarieren Sie diesen Kon- struktor wie einen normalen Konstruktor, lediglich ohne Sichtbar- keits-Modifizierer und mit dem Schlüsselwort static ....
Eine Kontoverwaltung könnte z.B.den aktuellen Zinssatz in einem statischen Konstruktor aus einer Datenbank auslesen"
"Statische Methoden können nicht auf die normalen (In- stanz-)Eigenschaften einer Klasse zugreifen.Das ist auch logisch, denn diese Eigenschaften werden erst im Speicher angelegt, wenn eine Instanz der Klasse erzeugt wird."Endlich fällt - wenn auch erst beim Thema static Konstruktoren - das klärende Wort: Man kann also aus static-Methoden nicht auf Instanz-Variablen zugreifen! Das hätte aber auch schon einige Absätze höher untergebracht werden können, denke ich mal.
"Ein statischer Konstruktor darf keinen Modifizierer für die Sichtbar- keit und keine Argumente besitzen.Neben einem statischen Kon- struktor können Sie natürlich auch normale Konstruktoren deklarie- ren. Statische Destruktoren sind übrigens nicht möglich."Und jetzt ist wieder alles klar für mich.
"Die while -Schleife überprüft die Schleifenbedingung im Kopf und wiederholt die enthaltenen Anweisungen so lange,wie diese Bedin- gung erfüllt ist:while (Bedingung ) { Anweisungen }Beachten Sie,dass diese Schleife nicht mit einem Semikolon abge- schlossen werden muss. Das folgende Beispiel zählt eine Variable hoch,solange diese einen Wert kleiner 10 besitzt:int i =1; while(i <10) { Console.WriteLine(i); i++; }Eine while -Schleife können Sie mit break explizit abbrechen.So kön- nen Sie Schleifen erzeugen,die ihre Bedingung im Körper überprü- fen:i =0; while (true) { i++; if (i >9)break; Console.WriteLine(i); }Solche Schleifen benötigen Sie dann,wenn die Bedingung so kom- plex ist,dass diese nicht im Kopf oder Fuß der Schleife überprüft wer- den kann.
3.6.4 Die do-Schleife
Die do -Schleife überprüft die Bedingung im Fuß:do Anweisungen while (Bedingung );Im Unterschied zur while -Schleife wird die do -Schleife mindestens einmal durchlaufen,auch wenn die Bedingung zu Anfang der Schleife bereits falsch ist.Das folgende Beispiel lässt den Anwender eine Ant- wort eingeben und schleift solange,bis dieser die »richtige « Antwort eingegeben hat:string answer; int i =0; do { i++; if (i <3) Console.Write("Geben Sie die Antwort ein:"); else Console.Write("Geben Sie die Antwort ein "+ "(Tipp:Die richtige Antwort ist 42):"); answer =Console.ReadLine(); } while (answer !="42");Wie eine while -Schleife,können Sie eine do -Schleife explizit mit break abbrechen:i =0; do { i++; if (i >9)break; Console.WriteLine(i); } while (true);"
"Die statischen Methoden haben wir bereits kennen gelernt, und wir wissen mittlerweile, dass wir für deren Verwendung keine Instanz der Klasse erzeugen müssen. Man sagt auch, die Attribute einer Klasse, die als static deklariert sind, sind ein Bestandteil der Klasse selbst; die anderen Attribute sind nach der Instanziierung Bestandteile des jeweiligen Objekts."Okay, ist wirklich klar formuliert.
"Das bedeutet auch Folgendes: Wenn mehrere Instanzen einer Klasse erzeugt wurden und in jeder dieser Instanzen wird eine statische Methode aufgerufen, dann ist das immer dieselbe Methode - sie ist nämlich Bestandteil der Klassendefinition selbst und nicht des Objekts. In Abbildung 3.3 wird im Bild dargestellt, wie sich das Ganze verhält."...
"überlegen wir doch einmal, wie es dann mit den Variablen bzw. Feldern der Klasse aussieht. Wenn eine Variable als static deklariert ist, also Bestandteil der Klasse selbst und nicht des aus der Klasse erzeugten Objekts ist, dann müsste diese Variable praktisch global gültig sein - über alle Instanzen hinweg....
Exakt so ist es. Ein Beispiel soll uns das verdeutlichen. Für dieses Beispiel wird ein Fahrzeugverleih angenommen, der sowohl Fahrräder als auch Motorräder als auch Autos verleiht. Der Besitzer will nun immer wissen, wie viele Autos, Fahrräder und Motorräder unterwegs sind. Wir erstellen also eine entsprechende Klasse Fahrzeug , aus der wir dann die entsprechenden benötigten Objekte erstellen können..."
"Die Variable anzVerliehen zählt unsere verliehenen Fahrzeuge. Mit den beiden Methoden Ausleihen()und Zurueck(), die beide als public deklariert sind, können Fahrzeuge verliehen werden. Die Methode GetAnzahl()schließlich liefert die Anzahl verliehener Fahrzeuge zurück, denn die Variable anzVerliehen ist ja als private deklariert (Sie erinnern sich: ohne Modifikator wird in Klassen als Standard die Sichtbarkeitsstufe private verwendet)....
Damit funktioniert unsere Klasse bereits, wenn wir eine Instanz davon erstellen. Doch nun will der Fahrzeugverleih auch automatisch eine übersicht aller verliehenen Fahrzeuge bekommen. Nichts leichter als das. Wir fügen einfach eine statische Variable hinzu und schon haben wir einen Zähler, der alle verliehenen Fahrzeuge unabhängig vom Typ zählt."
"Als Letztes wollen wir nun noch eine Methode hinzufügen, mit der wir erfahren können, wie viele Fahrzeuge insgesamt verliehen sind. Wenn wir die statische Variable anzGesamt nämlich veröffentlichen würden, könnte sie innerhalb des Programms geändert werden. Das soll aber nicht erlaubt sein. Also belassen wir es bei der Sichtbarkeitsstufe private und fügen lieber noch eine Methode hinzu, die wir ausnahmsweise ebenfalls statisch machen."...
"Innerhalb einer statischen Methode können Sie nur auf lokale und statische Variablen zugreifen. Die anderen Variablen sind erst verfügbar, wenn eine Instanz der Klasse erzeugt wurde, und da das nicht Voraussetzung für den Aufruf einer statischen Methode ist, können Sie die Instanzvariablen auch nicht verwenden."Naja, das ist ein Hinweis, der gut angebracht ist, könnte aber noch klarer formuliert werden, etwa so:
"In C# ist es nicht möglich, 'richtige' globale Variablen zu deklarieren, weil alle Deklarationen innerhalb einer Klasse vorgenommen werden müssen. Ohne Klassen geht es hier nun mal nicht. Durch das Konzept der statischen Variablen haben Sie aber die Möglichkeit, dennoch allgemeingültige Variablen zu erzeugen.Okay, ist klar, aber ein Warnhinweis wäre vielleicht angebracht, dass man auf diese Weise fern ab von jeglicher OOP geraten kann...
Deklarieren Sie einfach eine Klasse mit Namen G oder Global , in der Sie alle globalen Variablen zusammenfassen. Deklarieren Sie diese als statische Felder und ermöglichen Sie es allen Programmteilen, auf die Klasse zuzugreifen."
"Statische Methoden und Variablen sind wie bereits gesagt Bestandteil der Klasse selbst. Das bedeutet, dass auf sie anders zugegriffen werden muss als auf Instanzmethoden bzw. -variablen. Sehen wir uns die folgende Deklaration einmal an"...
"Die Methode SCompare()ist eine statische Methode, die Methode Compare()eine Instanzmethode, die erst nach der Erzeugung einer Instanz verfügbar ist. Wenn wir nun auf die Methode SCompare()zugreifen wollen, können wir dies nicht über das erzeugte Objekt tun, stattdessen müssen wir den Bezeichner der Klasse verwenden, denn die statische Methode ist kein Bestandteil des Objekts - sie ist ein Bestandteil der Klasse, aus der wir das Objekt erstellt haben."Okay, noch einmal, warum nicht.
"Bei statischen Methoden wie auch bei statischen Variablen muss zur Qualifizierung der Bezeichner der Klasse selbst benutzt werden, da statische Elemente Bestandteil der Klasse und nicht des erzeugten Objekts sind.Zum ersten Mal wird es etwas wirrer:
Für Objekte gilt, dass über sie nur auf Instanzmethoden bzw. Instanz-variablen zugegriffen werden kann."
"Auch die do -Schleife (oder do-while -Schleife) ist abhängig von einer Bedingung. Anders als bei der while -Schleife wird hier der Code aber mindestens einmal durchlaufen, weil die Bedingung erst am Ende der Schleife kontrolliert wird, weshalb man auch von einer nicht-abweisenden Schleife spricht. Die Syntax der do -Schleife lautet wie folgt:do { //Anweisungen } while (Bedingung);Ein Beispiel für die Verwendung einer do -Schleife ist die Berechnung der Quadratwurzel nach Heron. Es handelt sich dabei um ein Annäherungsverfahren, das bereits nach einer kleinen Anzahl an Schritten ein verhältnismäßig genaues Ergebnis liefert.
Heron ging von folgender überlegung aus: Wenn ein Quadrat existiert, dessen Fläche meiner Zahl entspricht, muss die Kantenlänge dieses Quadrats zwangsläufig der Wurzel der Zahl entsprechen. Wenn ich also ein Rechteck nehme, bei dem eine Kante die Länge 1 besitzt und die andere Kante die Länge meiner Zahl hat, so hat dieses Recht-eck auch die gleiche Fläche. Alles, was nun noch zu tun bleibt, ist, das arithmetische Mittel zweier Kanten zu errechnen und daraus ein neues Rechteck zu bilden, bis es sich um ein Quadrat handelt- die errechnete Kantenlänge ist also dann die gesuchte Wurzel.
Das arithmetische Mittel lässt sich leicht berechnen, es handelt sich um eine einfache mathematische Formel. Unter der Annahme, dass ein Rechteck die Seiten a und b hat, die neuen Seitenlängen a' und b' lauten und die Fläche des Rechtecks mit A bezeichnet wird, lässt sich das arithmetische Mittel der Seiten a und b folgendermaßen errechnen:a'=(a+b)/2Die Errechnung der neuen Seite b' erfolgt über die Fläche, die uns ja bekannt ist:b'=A/a'Vorausgesetzt, dass wir eine Genauigkeit festlegen, bei deren Erreichen die Berechnung beendet werden soll, können wir die Wurzel einer Zahl mit einer einfachen do -Schleife berechnen. Im Beispiel steht die Konstante g f ür die Genauigkeit, die für unsere Berechnung gelten soll./*Beispielklasse do-Schleife (Heron)*/ /*Autor:Frank Eller */ /*Sprache:C#*/ using System; class Heron { public double doHeron(double a) { double A =a; double b =1.0; const double g =0.0004; do { a =(a+b)/2; b =A/a; } while ((a-b)>g); return a; } } class TestClass { public static void Main() { double x =0; Heron h =new Heron(); Console.Write("Geben Sie einen Wert ein:"); x =Console.ReadLine().ToDouble(); Console.WriteLine("Wurzel von {0}ist {1}", x,h.doHeron(x)); } }"
"static bedeutet, dass diese Methode nicht auf Objekte aufgerufen wird (hierzu später mehr).... S.86 Statische Methoden
Dieses Kapitel behandelt so genannte statische Methoden.Und hier haben wir schon das nicht so Gelungene and diesem Buch! Immer wieder wird auf eine spätere Erörterung verwiesen. Kann man das Ganze nicht thematisch so aufbauen, dass solche Vorgriffe und Auf-Später -Vertöstungen weitgehend vermieden werden können? Ich denke, dass dies andere Autoren bewiesen haben.
Die statischen Methoden von C# sind vergleichbar mit den Funktionen von C (bzw. mit den statischen Memberfünktionen von C++). Es handelt sich um Methoden, die unabhängig von Objekten aufgerufen werden können (Objekte werden erst im nächsten Kapitel behandelt)."
"Statische Methoden, so kann man grob formulieren, sind »gewöhnliche« Unterpro- gramme. Insofern fallen sie aus dem objektorientierten Konzept ein wenig heraus. Sie sollten auch nur in solchen Situationen genutzt werden, in denen die eigentlich »richtigen« objektorientierten Methoden nicht angewendet werden können. Eine zu häufige Benutzung solcher Methoden zeigt gewöhnlich, dass die Lösung nicht objektorientiert entworfen wurde."Guter Hinweis und danke für die 'normal'-Sprache in Anführungszeichen. Hilft mir jedenfalls auf primitive Weise zu verstehen; auch wenn wir alle wissen, dass es 'das Normale' an sich eigentlich gar nicht gibt oder geben sollte in unserem aufgeklärten Denken...
"Gleichwohl erscheint es sinnvoll, solche Methoden bereits vor dem eigentlich objekt- orientierten Teil zu beschreiben.Junge, kündige nicht so viel an, fang lieber direkt mit dem Erklären an!
Es wird gezeigt, wie Methoden aufgerufen werden können, die " ...
"Schließlich wird die Verwendung statischer Variablen definiert. Auch hier ist Vor- sicht angebracht: statische Variablen sollten möglichst wenig verwendet werden."Weitere Ankündigungen, aber immer wieder vermischt mit schon eigentlichen Teil- Aussagen und hinweisen, die dann beim eigentlichen Teil gar nicht mehr weiter aufgegriffen werden.
"Die Klasse MainApp enthält zusätzlich zur statischen Main-Methode zwei weitere Methoden: die void-Methoden F und G. Beide sind - wie auch die Main-Methode - als static definiert (sie werden also nicht in Bezug aufObjekte aufgerufen - hierzu später mehr!). Im Gegensatz zu Main sind sie nicht public - sie sind daher außerhalb der Klasse Mainapp nicht sichtbar (und somit auch nicht aufrufbar)."...
using System; class MainApp { static int a; ......
"Eine statische Variable ist annähernd dasselbe wie eine globale Variable in C. Sie existiert zur gesamten Laufzeit des Programms und ist prinzipiell aus allen Kontex- ten heraus ansprechbar."Sehr hilfreich für die immer größer werdende Anzahl an Leuten, die erst gar nicht mit C anfangen, wenn sie programmieren lernen. Aber das Buch richtet sich erklärtermaßen nicht an blutige Anfänger, muss ich zur Entschuldigung der Autoren anführen.
"Sie unterscheidet sich nur dadurch von globalen C-Variablen, dass sie im Namens- raum einer Klasse eingebettet ist. Das bedeutet dreierlei: Erstens kann sie öffenlich oder nicht öffentlich sein (die a-Variable von C ist öffenlich, die namensgleiche Variable von MainApp ist nicht öffentlich); zweitens können Variablen verschiedener Klassen den gleichen Namen besitzen; und drittens muss beim Ansprechen einer sol- chen Variablen, die in einer anderern Klasse als der aktuellen definiert ist, der Name dieser Variablen mit dem Namen der Klasse präfixiert werden."Präfixiert ? Pränatale Fixierung an die Mutter als Bezugsperson fördert später prämenstruelle posttraumatische Störungen des femininen Adoleszenz-Subjekts, oder so ...
"Man beachte, dass solche statischen Variablen nur dann verwendet werden sollten, wenn es nicht anders geht. Statische Variablen sind eigendich nicht objektorientiert wie auch statische Methoden eigentlich nicht objektorientiert sind."Okay, ich verspreche Euch hiermit: Nur gaaaanz-ganz selten, wenn es wirklich nicht anders geht, also wenn ich sonst nicht ein noch aus weiß, werde ich diesen static-Dreck anfassen, heiliges Programierer-Ehrenwort!
using System; class Konto { public int nr; public double bestand; } public static void Main() { Konto ko = new Konto(); ko.nr=4711; ko.bestand=3000; Console.WriteLine(ko.nr); Console.WriteLine(ko.bestand); }
"Die Verantwortung für das Drucken ihrer Objekte übernimmt jetzt die Klasse Konto selbst.
Die bislang statische Methode der MainApp-Klasse wurde in die Klasse Konto verla- gert:"
using System; class Konto { public int nr; public double bestand; public void DruckDich () { Console.WriteLine(this.nr); Console.WriteLine(this.Bestand) } } class MainApp { public static void Main() { Konto k1 = new Konto(); k1.nr=4711; k1.bestand=3000; Konto k2 = new Konto(); k2.nr=4712; k1.bestand=8000; k1.DruckDich(); k2.DruckDich(); } }
Bei der Verlagerung in die Klasse Konto wurden einige änderungen vorgenommen:
# Die Methode wurde umbenannt zu DruckDich.
# Die Methode ist nun nicht mehr static.
# Und die Methode hat (scheinbar) keinen Parameter mehr.
Tatsächlich hat auch diese Methode einen Parameter - nur wird dieser vom Com- piler automatisch generiert: Er ist vom Typ Konto (weil die Methode zur Klasse Konto gehört) und hat den Namen this. Der Parameter, der in der alten Lösung explizit definiert werden musste (und der dort als k bezeichnet worden war), wird bei nichtstatischen Methoden also automatisch vom Compiler generiert. Insofern wird dann auf die Attribute des zu druckenden Kontos auch nicht mehr über k, son- dern über this zugegrififen. Technisch ist alles beim Alten geblieben - nur die For- mulierung hat sich geändert.
Auch der Aufruf dieser Methode hat sich geändert. In der alten Lösung wurde die Referenz aufdas zu druckende Konto als Parameter an die statische DruckeKonto- Methode übergeben. Hier nun wird diese Referenz dem Namen der Methode voran- gestellt:"
k1.DruckDich (); k2.DruckDich ();
Natürlich wird auch hier der Inhalt der Referenz wieder an die Methode übergeben - und zwar an den this-Parameter dieser Methode.Okay, geht mir genau so, lieber merkwürdig, aber dafür merkfähig, also merkwürdig im eigentlichen Wortsinn.
Der Name DruckDich ist vielleicht etwas merkwürdig (kein Mensch würde in einem richtigen Programm natürlich diesen Namen nutzen). Aber er ist einigermaßen sug- gestiv: Man möchte einem Konto »Bescheid sagen«: hallo du da, Konto: druck dich! Und genau dies ist im Sinne der Objektorientierung."
"Noch einmal zurück zum this-Parameter, den automatisch alle nichtstatischen Methoden einer Klasse besitzen:Wirklich klare Erklärung - nicht mehr und nicht weniger, weiter so!
Innerhalb einer Methode einer Klasse existiert stets eine Referenz namens this.
Diese Referenz verweist innerhalb der Funktion auf dasjenige Objekt, für welches die Funktion aufgerufen wurde. "
"Beim Aufruf: k1.DruckDich() verweist this auf dasjenige Objekt, auf welches k1 verweist; beim Aufruf k2.DruckDich() verweist this auf dasjenige Objekt, auf welches k2 verweist. Man kann auch sagen, dass beim Aufruf diejenige Referenz, über welche die Methode aufgerufen wird, an this über- geben wird. this ist also ein Parameter der Funktion (der formale Parameter), an welchen die Referenz, auf die die Methode aufgerufen wird, als aktueller Parameter übergeben wird."Na, ist das nicht ein wenig holprig formuliert?
k1.DruckDich()
verweist this - in der Methode DruckDich (!) - auf dasjenige Objekt, für das k1 steht '...
"Anders gesagt: über this kann innerhalb der Methode dasjenige Objekt angespro- werden, für welches die Methode aufgerufen wird. Bezeichnet man dieses Objekt als das »aktuelle Objekt«, so kann man verkürzt sagen: mit this ist immer das aktuelle Objekt der Aufrufs gemeint (genauer: this ist eine Referenz auf das aktuelle Objekt)."Aah, dann hätte ich meine Ersatz-Formulierung ja sparen können! Hier steht alles noch viiiel treffender und mehrfach in anderen Worten gekleidet, bestens!
"Auf diese Weise ist die Methode allgemein: Sie kann den Zustand jedes beliebigen Objekts drucken. Genau das ist natürlich auch der Sinn der Sache."
druckeKonto (kl); druckeKonto (k2);
Naja, das hätte aber eine static-Methode mit dem K1 oder k2 als überzugebendem Parameter allerdings auch geleistet, oder?
"Die while-Schleifeusing System; class MainApp { public static void Main () { Console.Write("Exponent: "); int exponent= Convert.ToInt32 (Console.ReadLine() ); const int basis 0 2; int zaehler = 1; int ergebnis = basis; while (zaehler < exponent) { ergebnis = ergebnis * basis; zaehler = zaehler +1; } Console.WriteLine(ergebnis);Das obige Programm demonstriert die Verwendung der while-Schleife. Es berechnet eine beliebige Potenz von 2. Der Exponent wird eingegeben. Die Variable basis wird als const definiert. D.h., diese Variable muss unmittelbar bei ihrer Definition initialisiert werden. Ihr Wert kann später nur noch gelesen, nicht aber mehr geändert werden.
Die while-Schleife umfasst zwei Anweisungen. Diese Anweisungen müssen mit ge- schweiften Klammern zu einem Block zusammengefasst werden. Sofern nur eine einzige Anweisung wiederholt werden muss, braucht diese Anweisung nicht ge- klammert zu werden. Der Block, der mittels der geschweiften Klammern gebildet wird, fungiert nach außen hin wiederum als eine einzige Anweisung.
Eine while-Schleife ist also wie folgt aufgebaut:while (Ausdruck) Anweisung;"
"Wie Sie gesehen haben, können Methoden als statisch deklariert werden. Aber was ist eine statische Methode überhaupt? Wenn eine Methode mit dem Schlüsselwort static markiert wird, kann sie direkt auf Klasseneben aufgerufen werden, ohne dass eine Objektinstanz erforderlich ist. Aus diesem Grund wird Main() als static deklariert, damit das Laufzeitsystem diese Funktion aufrufen kann, ohne eine neue Instanz der definierenden Klasse zuweisen zu müssen. Diese Funktion ist sehr nützlich, da Sie sonst ein Objekt erstellen müssten, um ein Objekt zu erstellen, das ein Objekt erstellt (...)."Hurtig aber treffend vorgebracht!
public static string Complain() { string[] messages = new string[5]{"Do I have to?", "He started -it!", "I'm too tired...", "I hate school!", "You are sooo wrong."}; return messages[CetRandomNumber(5)]; }
"Der Aufruf einer statischen Methode ist einfach. Sie müssen lediglich den Member an den Namen der definierenden Klasse anhängen:"
public static void Main(string[] args) { for(int i =0; i < 40; i++) Console.WriteLine(Teenager.Complain()); }Was heißt hier 'den Member' ? Hier ist wohl ein Element gemeint, das zu einr Klasse gehört, und in diesem Fall eben unsere static Methode sein soll!
"Bei nichtstatischen Methoden (Instanzmethoden) handelt es sich um Methoden, die auf Objektebene gültig sind. Wenn Complain () nicht als static markiert wäre, müssten Sie eine Instanz der Teenager-Klasse erstellen, bevor Sie sich das folgende Gemeckere anhören können:"
Teenager joe = new Teenager(); joe.Complain();Das Beispiel ist ja eigentlich ganz gut gewählt. Lobenswert ist auch, dass der Autor überhaupt static und nicht-static Methode mit einem Beispiel in eben diesen zwei Varianten ablaufen lässt. Noch besser wäre es freilich, wenn die nicht-statische Methode nicht nur an das Objekt 'teenager Joe' gehängt wäre, sondern diese Methode eine Transformation bewirken würde, die bei Joe eben etwas anderes bewirkt als bei Jane - je nach dem, welche anderen Eigenschaften bei Joe und welche bei Jane zu finden sind... naja, vielleicht gehen meine Wünsche zu weit. Irgendwie verstehe ich hier noch nicht, was damit gewonnen ist. Methoden überhaupt andeers als static zu definieren.
"Zusätzlich zu statischen Methoden kann eine C#-Klasse auch statische Datenmember definieren. Denken Sie daran, dass eine Klasse normalerweise mehrere Zustandsdaten definiert. Dies bedeutet lediglich, dass jede Obiektinstanz eine interne Kopie der zu Grunde liegenden Werte verwaltet. Wenn Sie eine Klasse wie folgt definiert haben:"
class Foo { public int intFoo; }
"können Sie daher eine beliebige Anzahl von Objekten des Typs Foo erstellen und das IntFoo-Feld auf einen eindeutigen Wert festlegen:"
// jeder Foo-Verweis unterhält eine Kopie des IntFoo-Feldes. Foo f1 = new Foo(); f1.intFoo = 100; Foo f2 = new Foo(); f2.intFoo = 993;
"Statische Daten werden demgegenüber von allen Objektinstanzen gemeinsam genutzt. Anstatt in jedem Objekt eine Kopie eines bestimmten Feldes zu speichern, wird ein statischer Datenpunkt genau ein Mal zugewiesen."...
"Beachten Sie, dass die Airplane-Klasse zwei Methoden definiert. Die statische GetNumber()-Methode gibt die aktuelle Anzahl der Airplane-Objekte zurück, die von der Anwendung zugewiesen wurden. GetNumberFromObject() gibt ebenfalls die statische Ganzzahl NumberInTheAir zurück. Da diese Methode aber nicht als statisch definiert wurde, muss der Objektbenutzer diese Methode aus einer Instanz von Airplane aufrufen."(Es folgt der Aufruf dieser Methoden und deren Ergebnis als Bildschirmausgabe)
"Wie Sie sehen können, verwenden (sehen) alle Instanzen der Airplane-Klasse denselben Datenpunkt. Dies ist der Kempunkt statischer Daten: Alle Objekte verwenden einen bestimmten Wert auf Klassenebene (und nicht auf Objektebene) gemeinsam."
"Die Schleifenkonstrukte while und do/while
Sie haben bereits gesehen, dass die for-Anweisung normalerweise verwendet wird, wenn bereits Kenntnisse über die Anzahl der Iterationen vorliegen, die durchgeführt werden sollen (z. B., Schleife durchlaufen, bis j > 20). Die while-Anweisung ist demgegenüber von Nutzen, wenn Sie nicht wissen, wie lange es dauert, bis eine Abschlussbedingung erfüllt ist.
Zur Veranschaulichung der while-Schleife werfen Sie nachstehend einen kurzen Blick auf die Dateibearbeitung in C# (die ausführlich in Kapitel 11 dargestellt wird). Die StreamReader-Klasse, die im System.IO-Namespace definiert ist, enthält die zum Lesen einer bestimmten Datei notwendigen Details. Sie erhalten eine Instanz des StreamReader-Typs als Rückgabewert der statischen File.OpenText()-Methode. Nachdem Sie die Datei config.win geöffnet haben, können Sie mit StreamReader.ReadLine() alle Zeilen in der Datei durchlaufen:try // Für den Fall, dass die richtige Datei nicht gefunden werden kann. { // Datei mit dem Namen 'config.win' öffnen. StreamReader strReader = File.OpenText("C:\\config.win"); string strLine; while (null != (strLine = strReader.ReadLine())) { Console.WriteLine(strLine); } // Datei schließen. strReader.Close(); catch(FileNotFoundException e) // Ausnahmen werden wir ausführlicher in Kapitel 3 kennen lernen. { Console.WriteLine(e.Message); }Eng verwandt mit der while-Schleife ist die do/while-Anweisung. Wie eine einfache while-Schleife wird do/while verwendet, wenn Sie eine Aktion mit einer unbekannten Häufigkeit durchführen müssen. Der Unterschied besteht darin, dass do/while-Schleifen den entsprechenden Codeblock garantiert mindestens ein Mal ausführen. Im Gegensatz dazu ist es möglich, dass eine einfache while-Schleife niemals ausgeführt wird, wenn die Abschlussbedingung von Beginn an falsch ist. Die Ausgabe der Iterationslogik ist in Abbildung 2.14 dargestellt.// Die do/while-Anweisung string ans; do { Console.Write("Are you done? [yes] [no] : "); ans = Console.ReadLine(); } while (ans != "yes");"
"Die Angabe static kann sowohl bei Datenelementen als auch bei Methoden gemacht werden und bewirkt, dass immer genau eine Instanz dieses Datenelementes oder dieser Methode existiert, unabhängig davon, wie viele Objekte existieren (und, ob überhaupt eines existiert)."Kurz und knapp, okay.; besonders der letzte zusatz gefällt mir: "..ob überhaupt eines existiert".
"Statische Datenelemente können beispielsweise dazu verwendet werden, die Anzahl der von einer Klasse erzeugten Objekte zu zählen, indem die Variable beim Anlegen eines neuen Objektes durch den Konstruktor automatisch um eins erhöht wird. Dadurch, dass das Datenelement in jedem Fall nur genau einmal existiert, ist sichergestellt, dass alle Objekte auf das selbe Datenelement zugreifen. "Wieso 'in jedem Fall' ? Also etwa genau einmal pro Fall, oder was? Oder ist 'auf jeden Fall' gemeint? Und wieso sollten die Objekte gemeinsam auf eine solches Klassen-Element zugreifen? Um sich selbst zu zählen? Es wurde doch eben noch formuliert, dass statische Datenelemente unabhängig von etwaigen Instanzen existieren können.
"Werden in einem Programm nun beispielsweise vier Objekte der Klasse CZaehler angelegt, so gibt jedes Objekt bei seiner Erstellung auf dem Bildschirm aus, das wievielte dieser Klasse es ist. "
ErstesObjekt = new CZaehler(); ZweitesObjekt = new CZaehler(); DrittesObjekt = new CZaehler(); ViertesObjekt = new CZaehler();Wieso wird hier die Klasse 'CZaehler' genannt? Das ist natürlich nicht falsch, aber ist das wirklich hilfreich, um ein anschauliches Beispiel vor Augen zu stellen? Die Klasse soll ja bestimmt für irgendetwas anderes stehen, als dass irgendwelche Objekte erstellt werden, deren höchste Aufgabe darin besteht, gezählt zu werden, nicht wahr?
"Statische Datenelemente kommen in der Praxis nicht sehr oft vor, aber falls einmal eine entsprechende Funktionalität benötigt wird - nämlich, dass alle Objekte gemeinsam auf einen gemeinsamen Wert zugreifen - , so bieten sie eine sehr elegante Lösung."Ne-nee, das mit dem 'gemeinsam zugreifen' ist so eine Sache: Das kann zwar sein (zB summiere meinen Betrag mit dem der anderen auf und lege mich nur an, wenn es diesen Betrag noch nicht gibt) , es kann aber auch sein, dass es eine übergeordnete Verwaltung gibt, die auf diese Objekte zugreifen soll (zählen, den höchsten ermitteln, ...) .
"Statische Methoden hingegen kommen in der Praxis etwas öfter vor. Ihr Sinn besteht darin, eine Methode auch aufrufen zu können, ohne vorher ein Objekt der entsprechenden Klasse anlegen zu müssen. Deswegen ist beispielsweise die Main-Methode statisch, da von der Klasse, in der Sie enthalten ist, nie ein Objekt angelegt wird. Damit die Funktion trotzdem existiert und aufrufbar ist, muss sie als statisch definiert werden."Okay
"Wie bei den Objekten haben Sie auch schon mit weiteren statischen Methoden gearbeitet, ohne es zu wissen. Beispielsweise ist der Befehl für die Bildschirmausgabe, WriteLine, eine statische Methode der Klasse Console, wie oben bereits erwähnt wurde: Sie legen nämlich nie ein Objekt der Klasse Console an, sondern verwenden die Klasse immer so, als sei sie bereits ein Objekt. Auch diese Funktionalität wird durch das Schlüsselwort static ermöglicht.Gutes Beispiel, okay.
"In diesem Kapitel werden Sie lernen, was Schleifen sind und welche Arten von ihnen es in C# gibt.Entschuldigung, dass ich mich hier npch einmal zu Wort melde, aber ich kann diesen Ankündigungsstil nicht unkommentiert stehen lassen. Denn dieser zieht sich durch das ganze Buch. Zwei Sätzchen zur Einstimmung am Anfang jedes Kapitels, damit der Leser nicht gleich erschrickt vor der ungwohnten Materie und dann noch 2 Sätzhcen beim Abspann, um noch einmal zu rekapitulieren, wa man verdaut hat... Ich halte nichts von dieser Marotte, auch wenn sie lieb gemeint ist!
Einleitung
Nachdem Sie im letzten Kapitel bereits gelernt haben, wie Sie den linearen Ablauf von Programmen mit Entscheidungen durchbrechen können, lernen Sie nun noch eine weitere Technik dazu kennen."
"Schleifen dienen dazu, Anweisungen wiederholt auszuführen, wobei entweder eine bestimmte Anzahl vorgegeben wird oder der Ablauf dynamisch gesteuert werden kann.
...
Die while-Schleife
Der Nachteil der for-Schleife ist, dass von vornherein feststehen muss, wie oft sie durchlaufen werden soll. Eine Schleife, die so lange läuft, bis (irgendwann) ein bestimmtes Ereignis eintritt, ist so nicht zu realisieren. Für solche Aufgaben gibt es in C# die while-Schleife.
Im Kopf der while-Schleife wird ein Ausdruck übergeben, und so lange dieser wahr ist, wird die Schleife ausgeführt. Sie müssen aber darauf achten, dass die Bedingung auf jeden Fall irgendwann wahr werden kann, sonst befindet sich das Programm in einer Endlosschleife.using System; public class Kreis { public static void Main() { const double Pi = Math.PI; double Flaeche; int Radius = 1; bool NochmalBerechnen = true; while(NochmalBerechnen) { Flaeche = 2 * Pi * Radius * Radius; Console.Write("Der Kreis mit dem Radius {0} hat ", Radius); Console.WriteLine("die Fläche {0}!", Flaeche); Radius++; Console.Write("Möchten Sie die Fläche des "); Console.Write("nächsten Kreises berechnen (j / n)? "); if(Console.ReadLine() != "j") { NochmalBerechnen = false; } } } }Dieses Programm berechnet nacheinander die Flächen von Kreisen mit dem Radius 1, 2, 3, ... so lange, bis der Anwender eingibt, dass er keine weitere Fläche mehr berechnen möchte, also die Variable NochmalBerechnen auf false gesetzt wird. Beachten Sie bitte, dass hinter der while-Anweisung kein Semikolon kommt. Die geschweiften Klammern sind optional, solange der Schleifenkörper aus nur einer Zeile besteht.
Die Syntax der while-Schleife lautet also :while(Bedingung) { Anweisungsblock; }In einem Punkt verhält sich die while- genauso wie die for-Schleife, sie sind nämlich beide abweisend. Das heißt, dass die Schleife unter Umständen nicht ein einziges Mal durchlaufen wird. Das kann passieren, wenn die Bedingung von vornherein falsch ist.bool Bedingung = false; while(Bedingung) { ... }wird beispielsweise nie ausgeführt, da die Variable Bedingung von Anfang an den Wert false enthält. Genauso wenig wird die for-Schleifefor(i = 1; i > 100; i++) { ... }ausgeführt, da i am Anfang den Wert 1 hat, die Schleife aber ausgeführt werden soll, solange i größer als 100 ist.
Vielleicht ist Ihnen in dem Programm außerdem die Zeile const double Pi = Math.PI; aufgefallen. Hier wird eine Variable Pi vom Typ double definiert, aber zusätzlich mit dem Schlüsselwort const versehen. Dadurch kann der Wert von Pi im Lauf des Programms nicht mehr verändert werden, sondern Pi stellt eine Konstante dar.
Der Wert einer Konstanten muss ihr gleich bei der Deklaration übergeben werden, da Sie später nicht mehr schreibend auf die Konstante zugreifen können. Als Wert wird in diesem Fall Math.PI übergeben.
PI ist eine vom .net Framework vorgegebene Konstante, die in Math enthalten ist (so wie WriteLine in Console enthalten ist), Math wiederum ist System untergeordnet. Math enthält mathematische Funktionen und wichtige mathematische Konstanten wie Pi oder die Zahl e. Natürlich hätten Sie in dem Programm auch direkt mit System.Math.PI arbeiten können, statt diesen Wert der Konstante Pi zuzuweisen.
Die do-Schleife
Es gibt noch eine weitere Schleife in C#, die der while-Schleife sehr ähnlich ist, nämlich die do-Schleife. Sie unterscheidet sich von der while-Schleife nur in dem Punkt, dass sie nicht abweisend ist und somit auf jeden Fall mindestens ein Schleifendurchlauf stattfindet.using System; public class Kreis { public static void Main() { const double Pi = Math.PI; double Flaeche; int Radius = 1; bool NochmalBerechnen = true; do { Flaeche = 2 * Pi * Radius * Radius; Console.Write("Der Kreis mit dem Radius {0} hat ", Radius); Console.WriteLine("die Fläche {0}!", Flaeche); Radius++; Console.Write("Möchten Sie die Fläche des "); Console.Write("nächsten Kreises berechnen (j / n)? "); if(Console.ReadLine() != "j") { NochmalBerechnen = false; } } while(NochmalBerechnen); } }Dieses Programm hat genau die selbe Wirkung wie das Beispiel der while-Schleife, aber es ist mit einer do-Schleife programmiert. Die Syntax der do-Schleife lautet alsodo { Anweisungsblock; } while(Bedingung);Beachten Sie bitte, dass hinter dem do kein Semikolon steht, hinter dem while aber sehr wohl eines! Stünde hier keins, könnte der Compiler das Ende der do-Schleife und den Anfang einer while-Schleife nicht unterscheiden.
Auch wenn es nicht noch einmal ausdrücklich erwähnt wurde, funktionieren die break- und die continue-Anweisung in der while- und der do-Schleife auf die selbe Art und Weise wie bei der for-Schleife."
"Eine Klasse beschreibt ein Muster für die Erstellung von Objekten. Sie definiert dazu Attribute und Operationen, die den Objekten bei der Erzeugung mitgegeben werden. Damit besitzt jedes Objekt eine eigene Kopie dieser Attribute und Operationen."Leider zweideutig: 'Damit besitzt jedes Objekt eine eigene Kopie dieser Attribute und Operationen' - also eine exakte Kopie mit dem selben Inhalt? Nein! Nur ein gleicher Behälter wird angelegt. 'Kopie' trifft die Sache nicht.
"Es gibt jedoch auch spezielle Attribute und Operationen, die in einer Klasse nur ein einziges Mal existieren und für alle Objekte identisch sind. Diese so genannten Klassenattribute und Klassenoperationen werden den Objekten bei der Erzeugung nicht mitgegeben. Sie werden gekennzeichnet durch das Schlüsselwort static."'und für alle Objekte identisch sind' - wieso überhaupt für Objekte? Es funktioniert ja auch, ohne dass Objekte erstellt worden sein müssen.
"Eine Klassenoperation ist Ihnen bereits bekannt: die Main()-0peration. public static void Main(string[] args){. . .}"
"Das Schlüsselwort static schließlich markiert Main() als Klas- senoperation. Damit ist diese Operation zusätzlich über die Klas- se Start - und nicht nur über ihre Objekte - verfügbar. Das be- deutet, dass kein Objekt erzeugt werden muss, um die Main()- Operation aufzurufen."'Wieso zusätzlich? Ich dachte, dass gerade Main nur diesen einen Zweck erfüllt. Und auch für alle anderen gilt doch: Nur über die Klasse direkt ansprechbar, unabhängig von Objekten! Also alles andere als zusätzlich. Oder habe ich da irgendetwas noch nicht begriffen? ...
"Es muss also eine Möglichkeit geben, Operationen auszuführen, die nicht an Objekte gebunden sind. Hier bieten sich die Klassen als Trä- ger solcher Operationen an, da sie ja als Muster bereits existieren. Ge- nau aus diesem Grund ist die Main()-0peration eine Klassenoperation. Zu Beginn eines Programms existieren noch keine Objekte. Es gibt aber sehr wohl bereits Klassen, von denen genau eine immer eine Main()-Operation enthält, um den Startpunkt des Programms festzule- gen und die ersten Anweisungen zu definieren."Naja, hier wird es erst einmal klarer: 'nicht an Objekte gebunden'. Aber schon dozieren die Herren Doctores wieder daher: 'Hier bieten sich die Klassen als Träger solcher Operationen an, da sie ja als Muster bereits existieren...' Oh Mann! Wieso 'anbieten' ? Diskutieren wir jetzt locker mit, wie man eine Programmiersprache baut? Oder bietet sich realiter noch etwas anderes an?
"Darüber hinaus können Sie auch eigene Klassenoperationen und -attribute implementieren. Häufig werden diese dazu verwendet, Auf- gaben zu übernehmen, die alle Objekte einer Klasse betreffen."(Nun folgt ein Beispiel von Verkehrsampeln, das in seiner Originalität und in seiner Anschaulichkeit für mich noch das beste an diesem Buch ist).
"Das Beispiel der Ampel hat verdeutlicht, dass Sie gleichartige Objekte in C# nur ein einziges Mal in einer Klasse beschreiben müssen, um mit Hilfe dieses Musters anschließend beliebig viele Objekte erzeugen zu können. Die Klassendefinition ist daher möglichst allgemein gehal- ten. Sie soll für jede ihrer Exemplare Gültigkeit besitzen. Dadurch kann es im Programmverlauf zu Mehrdeutigkeiten kommen, bei denen nicht klar ist, worauf sich eine Anweisung bezieht. Folgendes Beispiel soll die Problematik verdeutlichen.
Die AnweisungmeineAmpel.SetRot(false)
ist eindeutig. Sie bezieht sich auf die Operation SetRot(), die zu dem Objekt meineAmpel gehört. Hat die Klasse Ampel beispielsweise die Struktur des folgenden Programmfragments, so bereitet auch die Aus- führung der Operation keine Schwierigkeiten. Die Anweisungen sind eindeutig:"
class Ampel { bool rot; public void SetRot(bool r) { rot = r; } }
"Der Aufruf meineAmpel .SetRot(false) setzt das Attribut rot auf den Wert des Parameters r. Diesem wiederum wird zuvor der Wert des Arguments des Operationsaufrufs (false) zugewiesen. Bisher wurden die Variablen in den Parameterlisten der Operationen stets mit wenig aussagekräftigen Namen bezeichnet. Das trägt nicht gerade zum Ver- ständnis des Programmcodes bei. Es gehört zu einem guten Program- mierstil/ Variablen sinnvolle verständnisfördernde Namen zu geben. Die bisher verwendeten Parameter r, ge und gr sollten daher besser als rot, gelb und gruen bezeichnet werden. Die Eindeutigkeit der Zuwei- sung geht jedoch verloren, wenn Sie die Operation aus dem obigen Programmfragment wie folgt ändern:"
bool rot; public void SetRot(bool rot); { rot = rot; // nicht eindeutig! }
"Die Mehrdeutigkeit tritt hier in Zeile 6 auf. rot bezeichnet sowohl ein Attribut von Objekten der Klasse Ampel, als auch einen Parameter. Nach dem Aufruf von meineAmpel .SetRot(false) tritt bei der Anweisung rot = rot ein Konflikt auf. Um dieser Problematik zu begegnen, gibt es das Schlüsselwort this. Es bezieht sich in einer Klassendefinition immer auf das aktuelle Objekt, für das eine Operation ausgeführt wird. In dem obigen Programmfragment lautet die Anweisung in Zeile 6 dann:"
this.rot = rot; //eindeutig!
"In dieser Form ist die Anweisung eindeutig: "Weise den Wert des Parameters rot dem Attribut rot des aktuellen Objekts (hier: meineAmpel) zu." Einige wichtige Grundkonzepte der objektorientierten Programmierung haben Sie damit schon erfahren."Oh Gott, irgendetwas verstehe ich hier nicht!
"Die do-while-Schleife - erst arbeiten, dann prüfen
Wenn wir vor dem Füllen in der Schleife die Karaffe entleeren, können wir sicher sein, dass mindestens eine Fülloperation erforderlich ist, um die Karaffe bis zum Fassungsvermögen zu füllen.kleine Karaffe leeren 1 I in kleine Karaffe einfüllen Ausgabe Füllmenge Solange. bis die kleine Karaffe voll istDas Struktogramm zeigt diese fußgesteuerte Schleife. Die erste Prü- fung, ob die beiden Anweisungen im Schleifenkörper, Füllen und Aus- gabe, ausgeführt werden, erfolgt erst nach dem ersten Schleifenlauf. Somit ist gewährleistet, dass die Schleife mindestens einmal durchlau- fen wird. Anders als bei der kopfgesteuerten Schleife, die durchlaufen wird, wenn die Schleifenbedingung wahr ist (so lange, wie ...) wird die fußgesteuerte Schleife durchlaufen, so lange die Schleifenbedingung nicht wahr ist (so lange, bis...).
Setzen Sie auch diesen Ablauf, der im Struktogramm festgelegt ist, in der Main () -Operation der Startklasse in ein C#-Programm um."// Listing 4.9 class Start { static void Main(string[] args) { Karaffe kleineKaraffe = new Karaffe(5), großeKaraffe = new Karaffe(7); kleineKaraffe.Leeren(); do { kleineKaraffe.Füllen(1); kleineKaraffe.Ausgeben(); } while(kleineKaraffe.IsVoll() );Nachdem die Anweisung in Zeile 7 die kleine Karaffe sicherheitshalber entleert, füllt die do-while-Schleife (Zeile 8-12) das Gefäß wieder nach und nach bis zum Fassungsvermögen. Eingeleitet durch das Schlüssel- wort do folgt die Blockanweisung des Schleifenkörpers, der die beiden Anweisungen zum Füllen und zur Ausgabe enthäIt. Die Schleifenbe- dingung in Zeile 12 wird exakt so festgelegt wie bei der while-Schleife. Das erstaunt ein wenig, wo doch das Struktogramm die Bedingung so formuliert, dass em Ausdruck, der true liefert, zum Verlassen der Schleife führt, C# jedoch bei true die Anweisungen des Schleifenkör- pers (noch einmal) ausführt. Damit befindet sich C# jedoch in guter Gesellschaft mit anderen Programmiersprachen.
Formal ist die do-while-Schleife der while-Schleife sehr ähnlich. Dabei kennzeichnet do lediglich die Schleife, ohne dass eine Prüfung der Schleifenbedingung erfolgt.
do Anweisung while (Ausdruck);
Neben den grundlegenden Wiederholungsanweisungen bietet C# noch zwei weitere kopfgesteuerte Schleifen an. Die beliebte for-Schleife wird hauptsächlich als Zählschleife eingesetzt. Darüber hinaus existiert die foreach-Schleife, die festgelegte Anweisungen für jedes Element einer Sammlung ausführt."
"Es ist manchmal sinnvoll, Mitglieder eines Objekts zu definieren, die nicht mit einer spezifischen Klasseninstanz, jedoch mit der Klasse als Ganzes verknüpft sind. Solche Mitglieder werden als statische (static) Mitglieder bezeichnet."'Mitglieder eine Objektes?' Gehen da die Begriffe nicht ein wenig durcheinander? Solche Elemente gehören meiner Auffasung nach nicht zu Objekten, also zu Instanzen einer Klasse, sondern zu der Klasse direkt. Kann sein, dass der Autor mit 'Objekten' KLasse meint, dann würde ich es noch verstehen. Aber ich denke eher, dass er tatäschlich mit 'Objekten' Objekte als Klasseninstanzen meint, so unter dem Motto: was zu einer Klasse gehört, ist zunächst einmal ein Objekt. Und es gibt da noch etwas in einer Klasse, das ich folglich einfach erst einmal ebenfalls als einem Objekt zugehörig ansehe, aber dieses andere ist dann doch eher mit der Klasse als Ganzes und nicht einer Klasseninstanz (=Obkekt) verbunden.... Naja, entweder ich hab unklare Gedanken oder meine Gedanken werden bei solchen Definitionen unklar...
"Ein statisches Feld ist die einfachste Form eines statischen Mitglieds. Zur Deklaration eines statischen Feldes platzieren Sie einfach den Modifikator static vor der Variablendeklaration. Der folgende Code könnte beispielsweise dazu verwendet werden, die Anzahl der erstellten Klasseninstanzen zu verfolgen...."Okay, das typische Beispiel; aber wieso 'einfachste Form' ? Kommen denn mit static Methoden noch die intellektuellen Herausforderungen, auf die man erst einmal langsam vorbereitet werden muss? Ich denke doch, dass nicht.
"Die Erstellungsroutine für das Objekt erhöht den Instanzenzähler, und der Instanzenzähler kann referenziert werden, um die Anzahl der bisher erstellten Objektinstanzen zu ermitteln. Auf ein statisches Feld wird nicht über die Instanz der Klasse, sondern über den Namen der Klasse zugegriffen; dies gilt für alle statischen Mitglieder."'kann referenziert werden' - Mann, irgendwie klingt das recht hochgestochen; 'kann dann abgefragt oder angezeigt werden' oder so, würde doch auch schon genügen.
"Im vorangegangenen Beispiel wird ein internes Feld offen gelegt - eine nicht empfohlene Vorgehensweise. Das Codebeispiel kann so geändert werden, dass statt eines statischen Feldes eine statische Mitgliedsfunktion verwendet wird" ....
... public static int GetInstanceCount() { return(instanceCount); } static int instanceCount = 0; ... public static void Main() ... Console.WriteLine(MyClass.GetInstanceCount()); ...
"Mit diesem Code wird das gewünschte Ziel erreicht, und gleichzeitig wird das Feld den Benutzern der Klasse gegenüber nicht offen gelegt, d. h., die Flexibilität hinsichtlich zukünftiger Codeänderungen wird erhöht. Da es sich um eine statische Mitgliedsfunktion handelt, wird sie über den Klassennamen und nicht über den Namen einer Klasseninstanz aufgerufen.Na, ist das nicht ein bisschen kurz ausgefallen? Eigentlich müssten doch alle Methoden erst einmal static sein, im Sinne von nicht für jede Instanz kopiert werden, oder? Es gibt aber dennoch Methoden, die zur Laufzeit dem Objekt (=der bestimmten Klaseninstanz) zugeordnet sind, für die gerade diese Methode aufgerufen wird (also die 'normalen' Objekt-Methoden), und dann gibt es eben Methoden, die auf kein bestimmtes Objekt zeigen, sondern einfach nur der Klasse als Ganzes (oder als übergeordnetes oder als unabhängig von Objekten bestehendes) zugeordnet sind...
Im wirklichen Leben würde in diesem Fall wohl eher eine statische Eigenschaft verwendet. Diese werden in Kapitel 18, Eigenschaften, besprochen."
"Ebenso wie es statische Mitglieder gibt, gibt es auch statische Erstellungsroutinen. Eine statische Erstellungsroutine wird vor der Erstellung der ersten Objektinstanz aufgerufen und ist bei der Ausführung von einmalig anfallenden Setupaufgaben nützlich.
Eine statische Erstellungsroutine wird durch einfaches Hinzufügen von static vor der Erstellungsroutinendefinition deklariert. Eine statische Erstellungsroutine kann keine Parameter tragen."
class MyClass { static MyClass() { } }
"Es gibt zur Zerstörungsroutine keine analoge statische Zerstörungsroutine."Okay, nicht jeder Autor weist darauf hin. Der Zweck leuchtet mir bei dieser Formulierung ebenfalls ein.
"Da es in C# keine globalen Variablen oder Konstanten gibt, müssen alle Deklarationen innerhalb einer Klasse vorgenommen werden. Manchmal entstehen so Klassen, die vollständig aus statischen Mitgliedern bestehen. In diesem Fall besteht keine Veranlassung dazu, jemals ein Objekt der Klasse zu instanziieren. " (diese klare Sprache hätte ich mir von Anfang an gewünscht!) "Um eine Instanziierung zu verhindern, wird der Klasse eine private-Erstellungsroutine hinzugefügt."...
"Obwohl durch das Hinzufügen von private vor der Erstellungsroutinendefinition der tatsächliche Zugriff auf die Erstellungsroutine nicht geändert wird, wird durch die explizite Kennzeichnung deutlich, dass die Klasse über eine private Erstellungsroutine verfügen soll."'der tatächliche Zugriff nicht geändert' - hä? Meint er etwa: Den Ausdruck 'private' müssen Sie nicht ausdrücklich hinzufügen, da alles, was nicht anders definiert wird, grundsätzlich 'pivate' ist, aber es macht die Sache für den Leser des SourceCode noch deutlicher...?
"Die while-Schleife funktioniert wie erwartet: Solange die Bedingung zutrifft, wird die Schleife ausgeführt. Wie die if-Anweisung, erfordert while eine boolesche Bedingung:using System; class Test { public static void Main() { int n = 0; while (n < 10) { Console.WriteLine("Number is {0}", n); n++; } } }Die break-Anweisung kann dazu verwendet werden, die while-Schleife zu verlassen. Die state-Anweisung kann eingesetzt werden, um die schließende Klammer des while-Blocks für die Iteration zu überspringen und mit dem nächsten Durchlauf fortzufahren.using System; class Test { public static void Main() { int n = 0; while (n < 10) { if (n == 3) { n++; continue; } if (n == 8) break; Console.WriteLine("Number is {0}", n); n++; } } }Dieser Code erzeugt die folgende Ausgabe:
0 1 2 4 5 6 7
13.2.2 Do
Eine do-Schleife funktioniert wie eine while-Schleife, abgesehen davon, dass die Bedingung am Ende der Schleife und nicht zu deren Beginn ausgewertet wird:using System; class Test { public static void Main() { int n = 0; do { Console.WriteLine("Number is {0}", n); n++; } while (n < 10); } }Wie bei der while-Schleife, können die Anweisungen break und continue zur Steuerung des Schleifenablaufs eingesetzt werden."
"Bei einigen der bisher vervendeten Klassen des .NET Frameworks werden keine Instanzen der Klasse gebildet und dennoch die Metho- den und Eigenschaften genutzt, so beispielsweise bei den Klassen Sys- tem.String und System.DateTime. Das funktioniert, weil es sich um statische Klassen bzw. statische Elemente der Klasse handelt."Hey, das ist ein bisschen schnell darein geholpert! 'und dennoch die Metho- den und Eigenschaften genutzt' ? - Ja welche denn? Wachsen diese Methoden einfach so aus dem .NET Framework oder wie? Und welche Rolle spielt jetzt der interessierte Leser dabei? Soll er das einfach als Eigenart dieses Frameworks hinnehmen, oder soll er diese Eigenart nicht besser als Möglichkeit begreifen, um selber ganz bestimmte Dinge mit static zu regeln ?
"Auch für Ihre eigene Klasse können Sie so etwas realisieren, indem Sie Elemente der Klasse mit dem Schlüsselwort static definieren. Wenn Sie nur die Eigenschaft Pi lesen möchten, lohnt es in der Regel kaum, dazu eine Klasseninstanz zu erzeugen. Wenn Sie die Eigenschaft auch so verfügbar machen möchten, fügen Sie nach dem Schlüsselwort public das Schlüsselwort static ein."...
"Die Klasse verwenden
Wenn Sie die Klasse verwenden wollen, funktioniert das wie bei den Klassen des .NET Frameworks. Sie erzeugen eine Instanz der Klasse und können dann die definierten Elemente auf das Objekt anwenden. Die statische Eigenschaft müssen Sie dagegen direkt über den Namen der Klasse aufrufen."
clsMath objMath=new clsMath(7); MessageBox.Show("Exponent: " + objMath.Exp.ToString()); MessageBox.Show("'PI: " + clsMath.PI.ToString()); MessageBox.Show("Summe: " + objMath.Summe(1,3,6).ToString());Ich nix verstehen!!! Eine Instanz? Und dann die Elemente auf das Objekt anwenden? Bitte nicht so! Hier kann man doch nur erahnen, was gemeint ist, wenn man mindestens 3 andere Bücher über diese Thema gelesen hat, aber dann braucht man eben diesen kanppen Abriss gerade nicht mehr...
"Im Anschluss können Sie dann die Felder des Arrays füllen, indem Sie ihnen die Werte der Eingabefelder zuweisen. Sie werden von der Text- Eigenschaft des entsprechenden Feldes zurückgegeben. Der Ausdruck this.textBox1.Text gibt somit den Text des Textfeldes textBox1 zurück.Viiiiel zu knapp für mich, Helma!
Das »Objekt« this
Mit dem Schlüsselwort this können Sie auf eine Instanz der Klasse zugreifen, in der Sie dieses Schlüsselwort verwenden. Innerhalb einer Klasse, dievon System.Windows.Forms.Form abgeleitet wurde, können Sie damit also auf das Formular und seine Steuerelemente zugreifen."
"Schleifen
Schleifen dienen dazu, mehrere Anweisungen oder auch Methodenauf- rufe mehrfach nacheinander auszuführen. Wie jede andere Program- miersprache bietet auch C# mehrere Schleifenarten. Im Prinzip kann man mit jeder Schleife jedes Problem lösen. Die Frage ist nur, wieviel Aufwand dazu notwendig ist.
In der Regel sollten Sie die richtige Schleife für Ihren Zweck wählen, um mit minimalem Aufwand zum Ziel zu kommen. Dazu ist es natür- lich notwendig, einen überblick über die vorhandenen Schleifen zu bekommen.
Schleifentypen
Es gibt prinzipiell drei verschiedene Schleifentypen: abweisende Schleifen, nicht abweisende Schleifen und Zählschleifen. Der Unterschied liegt darin, wann die Schleifen verlassen werden und wann die Bedingung, die das Schleifenende bestimmt, überprüft wird.
Jede Schleife, ausgenommen Endlosschleifen, hat eine Bedingung, die bestimmt, wann die Schleife beendet wlrd. Sie wird Austritts- bzw. Eintrittsbedingung genannt. Bei einer abweisenden Schleife wird die Bedingung geprüft, bevor die Schleife das erste Mal betre- ten wird. Daher wird sie Eintrittsbedingung genannt, sie bestimmt nämlich, ob die Schleife betreten wird.
Jede Schleife, ausgenommen Endlosschleifen, hat eine Bedingung, die bestimmt, wann die Schleife beendet wird. Sie wird Austritts- bzw. Eintrittsbedingung genannt. Bei einer abweisenden Schleife wird die Bedingung geprüft, bevor die Schleife das erste Mal betre- ten wird. Daher wird sie Eintrittsbedingung genannt, sie bestimmt nämlich, ob die Schleife betreten wird.
Bei einer abweisenden Schleife kann es somit passieren, dass die Anweisungen innerhalb der Schleife nie durchlaufen werden. Das ist dann der Fall, wenn die Eintrittsbedingung nie erfüllt ist.
Im Gegensatz dazu werden die Anweisungen einer nicht abweisen- den Schleife immer mindestens einmal durchlaufen, weil erst danach die Austrittsbedingung überprüft wird. Ist sie erfüllt, wird die Schleife verlassen, ansonsten werden die Schleifenanweisungen wiederholt. Zählschleifen haben in der Regel eine Schleifenvariable, die bei jedem Schleifendurchlauf typischerweise um 1 erhöht oder verringert wird (oder um einen anderen Wert). Die Schleife wird so oft ausgeführt, bis der definierte Endwert für die Schleifenvariable erreicht wurde.
Egal, welchen Schleifentyp Sie wählen, müssen Sie darauf achten, dass irgendwann die Schleife korrekt verlassen wird. Andernfalls erhalten Sie eine Endlosschleife, die in der Regel nicht zum gewünschten Ziel führt, da sie nicht verlassen wird und damit ewig zuweisen, die in der Schleifenbedingung verwendet wird, sondern Sie müssen sicherstellen, dass die Schleifenaustrittsbedingung auch tatsächlich irgendwann erfüllt bzw. die Eintrittsbedingung nicht mehr erfüllt ist. Ein gutes Beispiel dafür ist der folgende Code. Scheinbar ist die Schleife zwar korrekt formuliert, trotzdem läuft sie endlos. Das liegt daran, dass die Variable intErg den Anfangs- wert 1 hat und in der Schleife mit sich selbst multipliziert wird. 1 * 1 bleibt aber 1, sodass die Schleifeneintrittsbedingung intErg <=1000 mmer erfüllt bleibt.int intErg=1; while(intErg<=1000) { intErg*=intErg; }(Listing 3.35: Fehlerhafte abweisende Schleife)
Abweisende Schleifen
Eine abweisende Schleife wird mit dem Schlüsselwort while eingeleitet. Danach folgt die Eintrittsbedingung, die immer in runde Klammern eingefasst werden muss. Das kann jeder boolesche Ausdruck sein. Die Eintrittsbedingung ist erfüllt, wenn der boolesche Ausdruck wahr ist. In diesem Fall wird die Schleife betreten und ihre Anweisungen werden ausgeführt.
Schleifenkopf, Schleifenfuß und Schleifenrumpf
Jede Schleife setzt sich aus dem Schleifenkopf, dem Schleifenrumpf und dem Schleifenfuß zusammen. Der Schleifenkopf besteht aus dem Schlüsselwort, das die Schleife einleitet, und gegebenenfalls der Ein- trittsbedingung. Der Schleifenrumpf enthält die Anweisungen, die innerhalb der Schleife ausgeführt werden. Der Schleifenfuß schließlich enthält die schließende Klammer und gegebenenfalls eine Austritts- bedingung.
In der abweisenden Schleife besteht der Schleifenkopf also aus dem Schlüsselwort while und der Eintrittsbedingung. Die Anweisungen der Schleife werden wieder in geschweifte Klammern eingefasst. Eine kor- rekt definierte abweisende Schleife könnte also wie folgt lauten:int intErg=2; while(intErg<=1000) { intErg*=intErg; } MessageBox.Show(intErg.ToString() );(Listing 3.36: Eine korrekte abweisende Schleife)
Hier wird die Schleife betreten, wenn die Variable intErg kleiner oder gleich 1000 ist. Innerhalb der Schleife wird die Variable mit sich selbst multipliziert und dann wieder der Variablen zugewiesen. Wenn diese Anweisung ausgeführt wurde. ist damit der Schleifenrumpf abgearbei- tet und die Eintrittsbedingung wird erneut geprüft. Wenn die Eintritts- bedingung erfüllt ist, wird der Schleifenrumpf erneut ausgeführt, ansonsten mit der Anweisung nach der Schleife fortgefahren. Hier führt dies zur Ausgabe des Berechnungsergebmsses.
Nicht abweisende Schleifen
Bei den nicht abweisenden Schleifen handelt es sich um solche Schlei- fen, die mindestens einmal durchlaufen werden, weil erst nach Ausfüh- ren des Schleifenrumpfes die Bedingung geprüft wird. Selbst wenn die Austrittsbedingung also schon beim ersten Durchlaufen der Schleife erfüllt ist, werden die Anweisungen im Schleifenrumpf ausgeführt.
In C# werden nicht abweisende Schleifen mit der do-while-Anweisung implementiert. Die Syntax lautet:do { } while (boolescher Ausdruck)Auch hier stehen die Anweisungen des Schleifenrumpfes innerhalb der geschweiften Klammern. Der boolesche Ausdruck stellt die Austrittsbe- dingung dar. Wenn er den Wert false hat, wird die Schleife verlassen. Sie wird also wiederholt, solange der boolesche Ausdruck den Wert true hat.intErg=2; do { intErg*=intErg; } while (intErg <= 1000); MessageBox.Show(intErg.ToString() );(Listing 3.37 Die Berechnung mithilfe einer nicht abweisenden Schleife)"