Arbeiten mit .NET: C-Sharp/ Grundlagen/ Bestandteile/ Variable

Aus Wikibooks

Variable sind die Grundlage dafür, wie mit Objekten gearbeitet wird.

Deklarieren[Bearbeiten]

Variablen bezeichnen Dinge, die im Verlauf des Programms durch Eingaben oder Zuweisungen ihren Wert verändern können. Sie stellen dazu einen Speicherplatz unter dem Namen der Variablen zur Verfügung, auf dem der jeweils aktuelle Wert der Variablen gespeichert wird. Unter .NET und damit unter C# sind Variablen typisiert: Das bedeutet, dass sie einen Speicherplatz bestimmten Umfangs – abhängig vom Typ der Variablen – zur Verfügung stellen.

Zusätzlich ist es von Bedeutung, wo im Arbeitsspeicher die Variable registriert wird. Das wird in den Kapiteln über Datentypen genauer besprochen.

Unter C# wird eine Variable wie folgt deklariert:

<Datentyp> <Name der Variablen>;

Mit dieser Anweisung wird dem Compiler mitgeteilt, dass es eine Variable dieses Datentyps geben soll. Es wird aber kein Objekt dieses Typs erzeugt; es wird nur gesagt, dass es ein solches Objekt geben soll. Die Variable muss initialisiert werden, also erstmals einen Wert erhalten, bevor sie wirklich existiert und verwendet werden kann. Insofern verhält sich C# anders als beispielsweise Visual Basic .NET.

Merke
Die Deklaration bereitet unter C# den Compiler nur auf die Verwendung der Variablen und des betreffenden Objekts vor. Erst mit der Initialisierung existiert die Variable.


Im Einstiegsprogramm Mein neues Auto haben wir unter anderem folgende Variable deklariert:

// in der Car-Klasse als Felder
	private int id;                   // Typ: int, also ganze Zahl
	private Color paint;              // Typ: Color, also eine Farbe
	private string type;              // Typ: string, eine Zeichenkette
	private bool isLeftSteered;       // Typ: bool, ein Wahrheitswert

	// in der ShowSignals-Methode der Car-Klasse 
	string result;

	// in der Main-Methode der Program-Klasse
	Car mycar = new Car(input, "998cm³ 44kW", 3);   // Typ: die Car-Klasse

Die letzte Deklaration ist mit der Initialisierung verknüpft, aber das ist – wie in den anderen Beispielen – nicht erforderlich.

Namen[Bearbeiten]

Im Prinzip ist der Programmierer ziemlich frei, wie er eine Variable benennen will. Es gibt aber natürlich ein paar Vorschriften.

Für Variablen unter C# gelten die folgenden Regeln.
  • Ein Bezeichner darf nur Buchstaben, Ziffern und den Unterstrich enthalten. Groß- und Kleinbuchstaben werden als verschieden angesehen.
  • Ein Bezeichner muss mit einem Buchstaben oder dem Unterstrich beginnen.
  • Ein Bezeichner darf nicht aus einem einzelnen Unterstrich bestehen.
  • Ein Bezeichner muss (innerhalb seines Gültigkeitsbereichs) eindeutig sein.
Die folgenden Varianten wären nicht zulässig.
  • Ein Bezeichner darf keine Leerzeichen, Bindestrich oder andere Sonderzeichen ($, %, & usw.) enthalten.
  • Ein Bezeichner darf kein Schlüsselwort sein. Kontextschlüsselwörter sind in manchen Situationen zulässig, sollten aber zurückhaltend verwendet werden. Nur value kommt oft in Frage.
  • Ein Bezeichner darf nicht übereinstimmen mit einer Methode oder einer Klasse.
Zusätzlich gibt es Empfehlungen.
  • Wählen Sie grundsätzlich beschreibende Namen, damit Ihr Code besser lesbar ist.
  • Ein Bezeichner sollte mit einem Kleinbuchstaben anfangen.
  • Kurznamen wie i, x, y sagen wenig aus. Sie werden üblicherweise nur als Schleifenvariable oder für Koordinaten verwendet.
  • Unter .NET ist es verpönt, dass ein Variablenname am Anfang seinen Typ enthält („ungarische Notation“).

Zur Erläuterungen erhalten Sie einige Beispiele für richtige, ungünstige und falsche Namen von Variablen:

// richtige Deklaration von Variablen
string result;
int i2;                // vorzugsweise für for-Schleifen u.ä.
bool isValid;
Color car_Painting;    // Unterstrich eigentlich nicht empfohlen, aber u.U. besser lesbar

// ungünstige, wenn auch zulässige Deklaration von Variablen
TextBox textBox23;     // kein beschreibender Name: Sinn dieser TextBox?
string stringResult;   // keine ungarische Notation
bool b;                // keine Einzelbuchstaben
decimal Salary;        // nicht mit Großbuchstaben anfangen

// falsche Deklaration von Variablen
int 2i;                // keine Ziffer am Anfang
string message Text;   // kein Leerzeichen
long salary%Tom;       // keine Sonderzeichen

Zusatzlich sind die .NET-Konventionen zur Namensvergabe zu beachten. Darüber hinaus raten wir von deutschen Begriffen ab, obwohl .NET und folglich auch C# deutsche Umlaute akzeptieren.

Initialisieren[Bearbeiten]

Unter „Initialisieren“ versteht man, dass einer Variablen erstmals ein Wert zugewiesen wird. Dies muss durch eine ausdrückliche Zuweisung erfolgen, aber es gibt mehrere Möglichkeiten:

  • durch die Zuweisung eines Literals, also eines konkreten Wertes
  • als Ergebnis einer Berechnung oder einer anderen Bearbeitung mehrerer Werte
  • als Ergebnis einer Methode
  • durch den Aufruf eines Konstruktors, sodass ein Objekt zurückgegeben wird

Diese Zuweisung kann unmittelbar bei der Deklaration, in einer der nächsten Zeilen oder an einer ganz anderen Stelle im Code stehen. Voraussetzung ist lediglich, dass die Variable an der betreffenden Stelle bekannt ist. Beispiele:

// Deklaration von Variablen ohne Initialisierung
string result;
bool isValid;
Color car_Painting;
decimal price;

// Deklaration von Variablen mit Initialisierung
decimal netPrice = 14.75m;                      // konkreter Wert
int i2 = 2; 
Car mycar = new Car(input, "998cm³ 44kW", 3);   // Konstruktor

// spätere Initialisierung
price = netPrice * 1.19m;                       // Berechnung
result = mycar.ToString();                      // Aufruf einer Methode
isValid = false;
car_Painting = Color.Blue;

Bitte vergleichen Sie die Definition der Car-Klasse: Die (internen) Felder werden am Anfang deklariert. Einige werden sofort initialisiert, die übrigen in einem der Konstruktoren.

Implizit typisierte Variable[Bearbeiten]

Wir haben betont, dass zu einer Variablen die Angabe des Typs gehört. Es gibt Situationen, in denen dies relativ umständlich ist; dann können wir mit dem Schlüsselwort var dem Compiler die Festlegung des Typs überlassen.

var netPrice = 14.75m;                          // decimal wegen des 'm' als Kennung
var i2 = 2;                                     // int als Standardwert für 2
var mycar = new Car(input, "998cm³ 44kW", 3);   // Car als Ergebnis des Konstruktor-Aufrufs
var result = mycar.ToString();                  // string als Rückgabewert dieser Methode

Bei dieser Art der Deklaration handelt es sich keinesfalls um eine Aufweichung des Prinzips, dass zu jeder Variablen ein bestimmter Datentyp gehört. Der Datentyp ist nicht etwa variabel; vielmehr trifft der Compiler eine konkrete Entscheidung nach dem Zusammenhang. Beachten Sie deshalb folgende Bedingungen:

  • Eine solche Deklaration ist nur möglich, wenn die Variable im gleichen Befehl auch initialisiert wird.
  • Der Typ, der in der Initialisierung zugewiesen wird, muss zum Zeitpunkt der Compilierung bekannt sein.
  • Eine solche Deklaration ist nur für lokale Variable (also innerhalb einer Methode oder eines Blocks) möglich, aber nicht für Felder oder Eigenschaften einer Klasse.
  • Jede solche Variable muss mit einem einzelnen Befehl deklariert werden.

Folgendes Vorgehen ist dagegen nicht zulässig:

 Fehlerhafte Festlegungen
var price;                 // woran soll der Compiler den Typ erkennen?
var i1 = 1, i2 = 2;        // keine mehrfache Deklaration

In späteren Kapiteln, in denen wir Variable mit „komplizierten“ Datentypen deklarieren (Arrays, Listen, anonyme Typen, Abfragen mit LINQ), werden wir diese Art der Deklaration intensiv nutzen.

Verwenden[Bearbeiten]

Eine Variable wird überall dort angegeben, wo das Objekt, das durch diese Variable bezeichnet wird, benutzt oder verändert wird. Das sind all die Stellen, an denen Anweisungen verwendet werden (die Beispiele sind aus dem vorigen Kapitel übernommen):

  • Zuweisung eines anderen Wertes an eine Variable
    area = Math.PI * Math.Pow(17, 2);
    
  • Zuweisung von Werten unter Benutzung des Wertes einer anderen Variablen
    double area = Math.PI * Math.Pow(radius, 2);
    
  • Aufruf einer Methode, bei der eine Variable als Argument übergeben wird
    area = Math.PI * Math.Pow(radius, 2);    // Math.Pow ist diese Methode
    
    Die Stelle, an der die Variable radius auftritt, gehört in doppelter Hinsicht zum Thema dieses Kapitels: Zum einen muss sie vorher deklariert worden sein und einen Wert erhalten haben. Zum anderen ist diese Methode mit zwei Variablen definiert, die innerhalb der Methode zur Berechnung der Potenz herangezogen werden, wobei der Wert von radius an die Variable x der Methode übergeben wird:
    public static double Pow( double x, double y ) { ... }
    
  • Aufruf einer Methode, die es für eine Variable gibt
    mycar.Accelerate(40);
    
  • Zuweisung des Ergebnisses einer Methode an eine Variable
    string output = mycar.ToString();
    
  • Benutzung des aktuellen Wertes in einer if-Abfrage oder einer switch-Verzweigung
    switch(temp) ... if(Speed == 0)          // aus der Lösung von Übung 5
    
  • als Schleifenvariable innerhalb einer for- oder einer foreach-Schleife
    foreach(char c in s)                     // die Verwendung von c in der Schleife
    

Sie sehen: Mit Variablen kann jederzeit problemlos gearbeitet werden. Wichtig ist, dass die Variable an der betreffenden Stelle bekannt ist. Das wird im nächsten Abschnitt angesprochen.

Gültigkeitsbereich[Bearbeiten]

Eine Variable steht immer nur innerhalb ihres Geltungsbereichs zur Verfügung. Man unterscheidet die folgenden Ebenen:

  • Unter C# existiert eine Variable niemals global im Programm, weil dies den Prinzipien der OOP widerspricht. Es gibt zwar einen Trick, dies mit statischen Variablen zu simulieren; aber es gibt fast niemals einen wichtigen Grund dafür. Also lassen Sie es.
  • Eine Variable kann global innerhalb einer Klasse gelten. Das trifft beispielsweise für die Felder zu: An jeder Stelle in der Klasse stehen sie zur Verfügung.
  • Eine Variable kann lokal innerhalb einer Methode gelten. Das gilt beispielsweise für die übergebenen Argumente, aber auch für andere Zwischenwerte, die nur in dieser Methode benötigt werden.
  • Eine Variable kann lokal innerhalb eines Blocks gelten. Das sind beispielsweise die Laufvariablen in for- und foreach-Schleifen. Es ist aber auch möglich, eine Variable innerhalb eines if-Zweigs zu deklarieren und nur dort zu benutzen.

Außerhalb dieses Bereichs steht eine Variable nicht zur Verfügung: Sie ist dort unbekannt; ihr Wert kann nicht genutzt werden.

Das führt zur Frage, wo eine Variable deklariert werden sollte. Dafür gilt vorrangig die Frage der Lesbarkeit:

  • Eine Variable, die nur innerhalb eines winzigen Code-Teils benötigt wird, sollte dort deklariert werden.
  • Eine Variable, die als var deklariert wird, kann erst dort deklariert werden, wo sie (erstmals) einen Wert zugewiesen bekommt.
  • Andere lokale Variable sollten möglichst zusammenhängend am Anfang eines Code-Teils deklariert werden. (Sonst muss man sich ihre Bedeutung immer erst zusammensuchen.)
  • Auch Klassenvariablen sollten innerhalb der Klasse an einer sinnvollen Stelle stehen.
Lebensdauer

Vom Geltungsbereich hängt direkt die Lebensdauer einer Variablen ab:

  • Eine lokale Variable wird ungültig, sobald der Geltungsbereich (Methode oder Block) verlassen wird.
  • Eine Klassenvariable wird ungültig, sobald das Objekt, dessen Teil sie ist, ungültig wird. (Gemeint ist eine Variable innerhalb der Klasse, nicht die Variable, die das Objekt selbst bezeichnet.) Für statische Variable ist diese Feststellung anders zu formulieren; aber das würde noch zu weit führen.

Sie können sich also merken: Dort, wo die Variable unbekannt wird, wird sie ungültig und dem Garbage Collector übergeben. Dies hat auch praktische Auswirkungen, wie die folgende Schleife zeigt, bei der ein String-Array arr geprüft werden soll:

for(int x1 = 0; x1 < 10; x1++ )
{
   string temp = arr[x1];
}

Vor und nach der Schleife ist der Wert von temp unbekannt. Außerdem – und das soll jetzt betont werden – wird in jedem Durchgang der Schleife unter dem Namen temp ein neuer (!) String vorgemerkt; der Wert aus dem vorherigen Durchgang steht nicht zur Verfügung.

Überdeckung

Oben hieß es schon, dass der Name einer Variablen innerhalb ihres Geltungsbereichs eindeutig sein muss. Was bedeutet das aber, wenn es innerhalb einer Klasse eine Variable gibt und in einer Methode eine neue Variable den gleichen Namen bekommt? Dann gilt:

  • Die lokale Variable überdeckt die Variable aus dem umfassenden Bereich und hat Vorrang.

Ändern wir das vorstehende Beispiel:

string temp = "Ein zweiter Versuch";
for(int x1 = 0; x1 < 10; x1++ )
{
   string temp = arr[x1];
}

Innerhalb der Schleife gibt es eine weitere Variable namens temp (und zwar weiterhin in jedem Durchgang eine neue). Innerhalb der Schleife kann aber nicht auf den Wert der außerhalb deklarierten temp-Variablen zugegriffen werden.

Zusammenfassung[Bearbeiten]

Mit Variablen werden Objekte im Programm benutzt:

  • Die Deklaration mit Datentyp und Name der Variablen teilt dem Programm mit, welche Art von Objekt benutzt werden soll.
  • Die Initialisierung stellt den entsprechenden Arbeitsspeicher zur Verfügung und weist einen Anfangswert zu.
  • Durch spätere Zuweisungen kann ein anderer Wert unter derselben Variablen gespeichert werden.

Eine Variable steht immer nur innerhalb ihres Geltungsbereichs zur Verfügung.

Übungen[Bearbeiten]

Übung 1 Definitionen Zur Lösung

Welche der folgenden Aussagen sind wahr, welche sind falsch?

  1. Der Wert eines Objekts wird Variable genannt.
  2. Durch eine Variable wird eine Stelle im Arbeitsspeicher gekennzeichnet, an der ein Objekt mit seinem Wert gespeichert ist.
  3. Zur Definition einer Variable gehört immer die Angabe des Datentyps.
  4. Zur Definition einer Variable gehört immer die Festlegung eines Wertes.
  5. Ein Objekt unter dem Namen einer Variablen wird erzeugt durch die erstmalige Zuweisung eines Wertes.
  6. Deklaration und Initialisierung einer Variablen gehören unter C# immer zusammen.
  7. Mit dem Schlüsselwort var wird eine Variable gekennzeichnet, die ihren Typ zur Laufzeit eines Programms ändern kann.

Übung 2 Variable benennen Zur Lösung

Welche der folgenden Namen von Variablen sind zulässig und geeignet, welche sind zulässig, aber ungeeignet, und welche sind unzulässig?

3rd_circle  _  Adelsprädikat  apfel  apple  b3  button2  customerTablePrenameRow  default  firstParagraph  guitar-music  i2  list1  next_step  s1  stringNachname  x

Übung 3 Gültigkeitsbereich und Lebensdauer Zur Lösung

Welche der folgenden Aussagen sind wahr, welche sind falsch?

  1. Eine Variable kann global im gesamten Programm verwendet werden.
  2. Eine Variable kann global in einer Klasse verwendet werden.
  3. Eine Variable kann lokal in einer Methode verwendet werden.
  4. Eine Variable kann eng begrenzt in einer Schleife verwendet werden.
  5. Alle Variablen können gemeinsam am Anfang eines Programmteils (Klasse, Methode, Block) deklariert werden.
  6. Alle Variablen können gemeinsam am Ende eines Programmteils (Klasse, Methode, Block) deklariert werden.
  7. Eine Variable kann mitten in einem Programmteil (Klasse, Methode, Block) deklariert werden.
  8. Wenn in einem Block verschiedene Variablen mit gleichem Namen zusammentreffen, wird immer die Variable aus dem größeren Bereich verwendet.
  9. Eine Variable bleibt solange gültig, bis sie explizit für ungültig erklärt wird.

Übung 4 Variable verwenden Zur Lösung

Welche der folgenden Verwendungen von Variablen sind zulässig, welche sind zwar zulässig, aber ungeeignet oder unvollständig, welche sind unzulässig?

Hinweise: Ungeeignete Bezeichner können Sie ignorieren, diese werden in Übung 2 behandelt. Die Punkte 6–8 beziehen sich auf die Car-Klasse aus dem Einstiegsprogramm.

  1. double speed = 36.0;
    
  2. length = 1.85
    
  3. double weight;
    
  4. double bmi = weight / (length * length);
    
  5. // berechne die Fakultät von 1, 2, 3...9
    for(i3 = 1; i3 < 10; i3 = i3+1)
    { int factorial = factorial * i3;
      Console.WriteLine( i3.ToString() + " Fakultät ist " + factorial.ToString() );
    }
    
  6. Console.WriteLine(mycar.speed);
    
  7. mycar.ShowSignals();
    
  8. if( mycar.NumberOfSeats = 0 ) Console.WriteLine("Ein Auto ohne Sitze ist kein Auto!");
    

Übung 5 Variable verwenden Zur Lösung

Schreiben Sie jeweils ein paar Code-Zeilen für die folgenden Situationen. (Sie beziehen sich auf die Car-Klasse und auf die Beispiele in diesem und im vorigen Kapitel.)

  1. Notieren Sie bei einem Rechteck Länge und Breite und berechnen Sie Fläche und Umfang.
  2. Es wird eine Variable für ein weiteres Auto benötigt: Typ "VW Caddy", 1600 cm3, Nummer 1483933.
  3. Schalten Sie bei diesem Fahrzeug das Warnblinklicht ein.
  4. Notieren Sie die aktuelle Geschwindigkeit dieses Fahrzeugs an einer neuen Stelle und geben Sie diesen Wert an der Console aus.
  5. Beschleunigen Sie dieses Fahrzeugs mit einer Abstufung von 6 km/h, bis die zulässige Geschwindigkeit innerorts erreicht oder überschritten ist.
Lösungen

Lösung zu Übung 1 Definitionen Zur Übung

Die Aussagen 2, 3, 5 sind wahr. Die Aussagen 1, 4, 6, 7 sind falsch.

Lösung zu Übung 2 Variable benennen Zur Übung
  • Folgende Namen sind zulässig und geeignet:
    apfel apple customerTablePrenameRow firstParagraph .
  • Folgende Namen sind zulässig, aber eher ungeeignet:
    • Adelsprädikat – möglichst kein Großbuchstabe am Anfang, keine Umlaute;
    • b3 – als Kürzel keine Aussagekraft;
    • button2 list1 – der Name beschreibt nicht die Funktion des Buttons bzw. der Liste;
    • i2 s1 x – als Kürzel keine Aussagekraft, nur in Sondersituationen akzeptabel: i2 oder x als Schleifenvariable, s1 als String innerhalb eines kleinen Blocks oder einer kurzen Methode
    • next_step – als Name einer Variablen eigentlich unproblematisch, entspricht aber nicht den .NET-Namenskonventionen;
    • stringNachname – keine ungarische Notation;
  • Folgende Namen sind nicht zulässig:
    • 3rd_circle – keine Ziffer am Anfang;
    • _ – kein einzelner Unterstrich;
    • default – keine Schlüsselwörter;
    • guitar-music – keine Sonderzeichen (hier: Bindestrich);

Lösung zu Übung 3 Gültigkeitsbereich und Lebensdauer Zur Übung

Die Aussagen 2, 3, 4, 5, 7 sind wahr. Die Aussagen 1, 6, 8, 9 sind falsch.

Lösung zu Übung 4 Variable verwenden Zur Übung
  1. Korrekte Verwendung der Variablen speed.
  2. Es fehlt das abschließende Semikolon. Die Deklaration von length fehlt ebenfalls; aber die könnte auch schon an einer früheren Stelle erfolgt sein.
  3. Als Deklaration in Ordnung. Irgendwo später muss die Initialisierung kommen; die ist Voraussetzung dafür, dass die Variable im nächsten Punkt verwendet werden kann.
  4. Als gleichzeitige Deklaration und Initialisierung der Variablen bmi in Ordnung – vorausgesetzt, dass die beiden Variablen weight und length korrekt vorbereitet wurden.
  5. Es ist notwendig, dass die Variable i3 deklariert ist. (Es ist möglich, aber nicht üblich, eine Schleifenvariable vorher zu deklarieren.) Die Variable factorial wird bei jedem Schleifendurchgang neu deklariert: Das passt nicht zur Aufgabenstellung, weil bei der Fakultät das vorherige Zwischenergebnis benötigt wird. Außerdem ist es falsch, weil rechts vom Gleichheitszeichen eine noch nicht initialisierte Variable verwendet werden soll. – Richtig wäre es, die Variable factorial vor der Schleife zu deklarieren und mit 1 zu initialisieren.
  6. Die Variable mycar darf verwendet werden, sofern sie vorher deklariert und initialisiert worden ist. Aber speed ist nur innerhalb der Klasse bekannt. Richtig wäre dieser Aufruf:
    Console.WriteLine(mycar.Speed);
    
  7. Korrekte Verwendung der Variablen mycar und ihrer (öffentlichen) Methode ShowSignals().
  8. Die Variable mycar darf verwendet werden, ebenso ihre (öffentliche) Eigenschaft NumberOfSeats. Im Code-Fragment wird dieser Eigenschaft ein Wert zugewiesen (das ist zulässig); aber dann wird abgefragt, ob der Wert dieser Eigenschaft true oder false ist. Eine Zahl soll wahr oder falsch sein? Nein, das ist nicht möglich. Falsch ist also in diesem Zusammenhang die Zuweisung eines Wertes; gemeint ist die logische Abfrage mit dem doppelten Gleichheitszeichen:
    if( mycar.NumberOfSeats == 0 ) Console.WriteLine("...");
    

Lösung zu Übung 5 Variable verwenden Zur Übung
  1. double length = 15.8, width = 7.3;
    double area = length * width;
    double extent = 2*length + 2*width;
    
  2. Car theCaddy = new Car("VW Caddy", "1600 cm³", 1483933);   // oder ein beliebiger anderer Name
    
  3. theCaddy.SetBothSignals(true);
    
  4. int currentSpeed = theCaddy.Speed;
    Console.WriteLine(currentSpeed);
    
  5. while(theCaddy.Speed < 50) theCaddy.Accelerate(6);
    

Siehe auch[Bearbeiten]

Wikipedia hat einen Artikel zum Thema Variable.

In folgenden Kapiteln der Buchreihe gibt es zusätzliche Informationen: