Erster C#-Kurs [] (Erster C#-Kurs), Lektion, Seite 723208
https://www.purl.org/stefan_ram/pub/erster_kurs_csharp (Permalink) ist die kanonische URI dieser Seite.
Stefan Ram
C#-Kurs

Erster C♯ -Kurs

Diese Seite enthält einen C♯ -Kurs von 2010. Seit 2015 wird an anderer Stelle ein neuere C#-Kurs aufgebaut.

>720785 Formatierungsregeln
Gleitkommazahlenliterale und Gleitkommazahlenwerte
»1E1«, »1D«
double=System.Double.
Übung Darstellung von »22E22«, Darstellung von »1234567890123456789012345678901234567890.0« mit und ohne ».0« am Ende
Dezimalbrüche
decimal, decimal myMoney = 300.5m, zum Wandeln nach double cast nötig
Namensräume, Klassen und Methoden (ähnlich wie Land, Ort und Straße). using-Direktive.
[Neu]using A = B.C;
Dokumentation lesen in C♯ 
Aufrufe
net library reference (".NET Framework Class Library"): http://http://msdn.microsoft.com/en-us/library/618ayhy6.aspx → System Namespace → Console Class → Console Methods → WriteLine-Method
Spezifikation und Implementation einer (abstrakten) Methode
Klienten (meist: variabel, Aufrufer) und Dienste (meist: vorgegeben, Aufgerufene), (Jedoch: IoC/Framework)
Übung Methode zur Ausgabe ohne Zeilenabschluß finden und verwenden
Zeichenliterale und Zeichenwerte
»Z«; »'Z'«
Steuersequenzen, char=System.Char.
Überladung von Methodennamen: WriteLine(Char)
Zahlenliterale und Zahlenwerte
—; »0«
int=System.Int32.
Übung Umwandlung von »0x2ECA«
Wertaufrufe
System Namespace: Math Class: public static double Round(double a)
System Namespace: Math Class: public static double Pow(double x, double y)
»void« als Ergebnistyp von WriteLine
Übung Programm berechnet das Maximum zweier Werte (Dokumentation der Klasse »System.Math« heranziehen)
Wahrheitsliterale und Wahrheitswerte
—; »true«, »false«
bool=System.Boolean
»System.Char.IsDigit( 'A' )«
Grundrechenarten
Ausdrücke können auch durch Operatoren (spezielle lexikalische Einheiten) und andere Ausdrücke, die dann Operanden genannt werden, geschrieben werden, Beispiel: »-2«
Grundrechenarten und Vorzeichen, Prioritäten, Klammern
Welchen Wert hat der Ausdruck »1 / 2 / 3«?
Ist der Wert des Ausdrucks »1.1 * 1.1« gleich dem Wert des Ausdrucks »1.21«? Welchen Wert hat der Ausdruck »1e20 + 1 - 1e20«?
Schreiben Sie möglichst kurze Ausdrücke für die folgenden Terme, ohne vorher irgendwelche Teile der Terme im Kopf auszurechnen.
4·5, 6 ÷ 7, 3³,
 1     3      3 + 4
--- - ---, -------
2 4 5 - 6
Die implizite Typanpassung
»1 * 1« hat Aufbau »int * int«
»1.1 * 1.1« hat Aufbau »double * double«
»1 * 1.1« hat zunächst Aufbau »int * double«, nach Wandlung dann »double * double«
»1.1 * 1« hat zunächst Aufbau »double * int«, nach Wandlung dann »double * double«
»'A' + 'A'« hat zunächst Aufbau »char + char«, nach Wandlung dann »int + int«
Der cast-Operator
Der unäre Operator »( int )« wird cast -Operator genannt. Er wird seinem Operanden wie ein Vorzeichen vorangestellt.
Der Ausdruck »( int )1.9« hat den Typ »int« und den Wert »1«.
An Stelle von »int« können auch andere Typen verwendet werden. Der Typ des gesamten Ausdrucks ist dann stets durch den cast -Operator bestimmt. Der Wert ergibt sich aus Umwandlungsregeln und ist im allgemeinen ein Wert, der dem Wert des Operanden „entspricht“.
Welchen Typ und Wert hat der Ausdruck »( double )( 1 / 2 )«?.
Beispiel:
System.Console.WriteLine( 65 );
System.Console.WriteLine( 'A' );
System.Console.WriteLine( ( char )65 );
System.Console.WriteLine( ( char )'A' );
System.Console.WriteLine( ( int )65 );
System.Console.WriteLine( ( int )'A' );
Vergleichsoperatoren
Es wurde schon gezeigt, wie Aussagen mit Aufrufen geschrieben werden können: »System.Char.IsDigit( 'A' )«.
Es gibt auch einige Operatoren zum Schreiben von Aussagen. Mit ihnen könne Aussagen über die Gleichheit oder die Größenbeziehung zweier Werte geschrieben werden.
==
!= <
> <=
>=
Beispiel:
System.Console.WriteLine( 2 < 1 );
Übungen:
Verwenden Sie den Operator »==«, um zu ermitteln, ob der Wert des Ausdrucks »1.1 * 1.1« gleich dem Wert des Ausdrucks »1.21« ist.
Verwenden Sie den Operator »==«, um zu ermitteln, ob der Wert des Ausdrucks »3.7« gleich dem Wert des Ausdrucks »( double )3.7« oder gleich dem Wert des Ausdrucks »( float )3.7« ist.
Verneinung
Der unäre Operator »!« kann einem Ausdruck mit einem Wahrheitswert vorangestellt werden. »!true« ist »false«, und »!false« ist »true«, »!( 2 < 1 )« ist »true«.
Falls »x« und »y« irgendwelche Ausdrücke sind, für die »!( x == y )« einen Wert hat, dann hat »x != y« denselben Wert, ist aber einfacher. Haben folgenden Ausdrücke auch Vereinfachungen?
0 »!( x != y )«
1 »!( x < y )«
2 »!( x <= y )«
3 »!!( x != y )«
Divisionrest
Für numerische Ausdrücke »x« und »y« ist »x % y« der Rest der Division von »x« durch »y«.
Prioritäten
Primär »x.y«, »f(x)«
Unär »+x«, »-x«, »(T)x«
Multiplikativ »x*y«, »x/y«, »x%y«
Additiv »x+y«, »x-y«
Vergleichend »x<y«, »x>y«, »x<=y«, »x>=y«
Gleichheitsprüfend »x==y«, »x!=y«
Eigenschaften
Ein Wertausdruck kann auch direkt durch einen Namen  angegeben werden. Eine Eigenschaft  einer Klasse ist solch ein Wertausdruck.
Beispiel: »System.DateTime.Now«
Im Vergleich zu einem Methodenaufrufe fehlen hier die runden Klammern.
Laufzeitwerte
Der Wert der Auswertung ein und desselben Ausdrucks muß nicht immer gleich sein.
Beispiel: »System.DateTime.Now«
Der Wert der Auswertung eines Ausdrucks kann daher im allgemeinen nicht  dem Ausdruck selber (zur „Schreibzeit“) entnommen werden, sondern er kann bei jeder Auswertung („Laufzeit“) ein anderer sein.
Nicht Ausdrücke haben Werte, sondern Auswertungen von Ausdrücken. Trotzdem spricht man abgekürzt von Wert eines Ausdrucks. Entsprechendes gilt auch für Wirkungen.
In »m(x)« wird der Methode »m« als Argumentwert also der Wert der Auswertung  von »x« übergeben.
Ausdrücke (Zusammenfassung)
Literale, Aufrufe, Operatorausdrücke und Eigenschaften sind Ausdrücke
Ausdrücke können zur Laufzeit ausgewertet werden
Parametertyp der WriteLine-Methode in der Dokumentation

Teil 2 Anweisungen

Schwerpunkt: imperative Programmierung

Die Ausdrucksanweisung
Die Häufigste Anweisung ist die Ausdrucksanweisung. Sie besteht aus einem Ausdruck und einem Semikolon. Bei ihrer Ausführung wird ihr Ausdruck ausgewertet (der Wert der Auswertung wird dabei aber nicht verwendet). Die Wirkung ihrer Ausführung ist somit die Wirkung der Auswertung ihres Ausdrucks.
Anweisungen
Die Auswertung eines Ausdrucks kann einen Wert ergeben und eine Wirkung haben. Neben den Ausdrücken gibt es auch noch Anweisungen. Sie werden zur Laufzeit ausgeführt. Die Ausführung einer Anweisung hat nur eine Wirkung, aber sie ergibt keinen Wert.
Die Blockanweisung
Die Blockanweisung besteht aus einer Folge von Anweisungen in geschweiften Klammern, die in der gegebenen Reihenfolge hintereinander ausgeführt werden.
Beispiel:
{ System.Console.WriteLine( 65 );
System.Math.Abs( 0 ); }
Übung Welche Ausgabe erzeugt das folgende Programm?
class Program
{ static void Main()
{ System.Console.WriteLine("one"); /* Eins *
System.Console.WriteLine("two"); * Zwei */ }}
Beispiel
class Program
{ static void Main()
{ { System.Console.WriteLine( "Auf einem Baum ein Kuckuck, -" );
{ System.Console.WriteLine("Sim sa la dim, bam ba,");
System.Console.WriteLine("Sa la du, sa la dim -"); }
System.Console.WriteLine("Auf einem Baum ein Kuckuck sass."); } { System.Console.WriteLine("Da kam ein junger Jaeger, -");
{ System.Console.WriteLine("Sim sa la dim, bam ba,");
System.Console.WriteLine("Sa la du, sa la dim -"); }
System.Console.WriteLine("Da kam ein junger Jaegersmann."); } { System.Console.WriteLine("Der schoss den armen Kuckuck, -");
{ System.Console.WriteLine("Sim sa la dim, bam ba,");
System.Console.WriteLine("Sa la du, sa la dim -"); }
System.Console.WriteLine("Der schoss den armen Kuckuck tot."); }}}
Übungen Endet jede Anweisung mit einem Semikolon?
Übungen Welcher der folgenden Texte ist: A) Eine Anweisung, B) ein Ausdruck oder C) keines von beidem?
0: »{}«
1: »;«
2: »{ System.Console.WriteLine( 0 ); }«
3: »{ 0 }«
4: »0«
5: »( 0 )«
6: »()«
7: »System.Console.WriteLine(0); System.Console.WriteLine(0);«
8: »{ System.Console.WriteLine(0);System.Console.WriteLine(0); }«

Deklarationen

Namenskonventionen
PascalCase für Namen, die außerhalb einer Klasse sichtbar sind (öffentliche Einträge einer Klasse)
Dieser Text verwendet zunächst deutschsprachige Namen. Im allgemeinen verwenden aber auch Muttersprachler der deutschen Sprache bevorzugt englische Namen, wenn sie viel programmieren.
Methodendeklarationen
class AufEinemBaumEinKuckuckSass
{ public static void RefrainAusgeben()
{ System.Console.WriteLine("Sim sa la dim, bam ba,");
System.Console.WriteLine("Sa la du, sa la dim -"); }

public static void Ausgeben()
{ { System.Console.WriteLine("Auf einem Baum ein Kuckuck, -");
RefrainAusgeben();
System.Console.WriteLine("Auf einem Baum ein Kuckuck sass."); } { System.Console.WriteLine("Da kam ein junger Jaeger, -");
RefrainAusgeben();
System.Console.WriteLine("Da kam ein junger Jaegersmann."); } { System.Console.WriteLine("Der schoss den armen Kuckuck, -");
RefrainAusgeben();
System.Console.WriteLine("Der schoss den armen Kuckuck tot."); }}}
Welche Ausgabe erzeugt der folgende Quelltext?
class Program
{ static void Gruessen()
{ System.Console.WriteLine("Hallo "); } static void ZweimalGruessen()
{ Gruessen(); Gruessen(); } static void ViermalGruessen()
{ ZweimalGruessen(); ZweimalGruessen(); } static void Main()
{ ViermalGruessen();
ZweimalGruessen();
Gruessen(); }}
Schreiben Sie ein Programm, das die folgenden Ausgabe erzeugt. Dabei soll aber jedes „Gemüsewort“ nur einmal im Quelltext vorkommen. Sich wiederholende Textteile der Ausgabe sollen sich also nicht im Quelltext wiederholen, es ist jedoch gestattet, daß sich Aufrufe wiederholen. Es soll also eine Methode für das deklariert werden, was sich wiederholt.
Tomaten
Rotkohl Gruenkohl
Lauch
Tomaten
Rotkohl Gruenkohl
Kohlrabi
Tomaten
Rotkohl Gruenkohl
Spinat
Rückgaben
Die Rückgabeanweisung besteht aus dem Schlüsselwort »return«, einem Ausdruck und einem Semikolon »;«. Die Ausführung der Rückgabeanweisung in einer Methode legt den Wert des Aufrufs dieser Methode fest.
  • »return x;«
class Program
{ public static int Wochentage(){ return 7; }
public static void Main()
{ System.Console.Write( "Zwei Wochen haben " );
System.Console.Write( 2 * Wochentage() );
System.Console.WriteLine( " Tage" ); }}
  • Anzahl der Wochentage, Tage in zwei Wochen
  • Mehrwertsteuersatz, Mehrwertsteuer von 23,32 Euro (23,32 Euro = Netto)
  • Anweisungen hinter der Rückgabeanweisung
Klassendeklarationen
PascalCase für Klassennamen
class AufEinemBaumEinKuckuckSass
{
public static void RefrainAusgeben()
{ System.Console.WriteLine("Sim sa la dim, bam ba,");
System.Console.WriteLine("Sa la du, sa la dim -"); } public static void Ausgeben()
{ { System.Console.WriteLine("Auf einem Baum ein Kuckuck, -");
RefrainAusgeben();
System.Console.WriteLine("Auf einem Baum ein Kuckuck sass."); } { System.Console.WriteLine("Da kam ein junger Jaeger, -");
RefrainAusgeben();
System.Console.WriteLine("Da kam ein junger Jaegersmann."); } { System.Console.WriteLine("Der schoss den armen Kuckuck, -");
RefrainAusgeben();
System.Console.WriteLine("Der schoss den armen Kuckuck tot."); }}}

class Vogelhochzeit
{ public static void RefrainAusgeben()
{ System.Console.WriteLine("Fi-di-ra-la-la, fi-di-ra-la-la, fi-di-ra-la-la-la-la!"); } public static void Ausgeben()
{ System.Console.WriteLine("Ein Vogel wollte Hochzeit machen, in dem gruenen Walde.");
RefrainAusgeben();
System.Console.WriteLine("Die Drossel war der Braeutigam, die Amsel war die Braute.");
RefrainAusgeben();
System.Console.WriteLine("Die Lerche, die Lerche, die fuehrt die Braut zur Kerche.");
RefrainAusgeben(); }}

class Program
{ static void Main()
{ AufEinemBaumEinKuckuckSass.Ausgeben();
Vogelhochzeit.Ausgeben(); }}
Übung Erweitern Sie die Klasse »AufEinemBaumEinKuckuckSass« und die Klasse »Vogelhochzeit« um jeweils eine Methode »NameAusgeben«, die den Namen des jeweiligen Liedes ausgibt. Die schon vorhandenen Methoden dieser beiden Klassen sollen dabei nicht verändert werden. Rufen Sie diese Methoden in sinnvoller Weise in der Hauptmethode »Main« auf.
Getrennte Übersetzung
Variablendeklarationen
  • statische Klassenvariablen, Zugriffe von innen/außen, Vergleich mit Methoden und Eigenschaften
  • Blockvariablen
  • Vergleich mit Literalen
  • Zusammenspiel mit Klassenvariablen
  • Typwandlung bei Initialisierung
  • Folge von Blöcken mit gleichen Variablennamen
  • Verschachtelung von Blöcken
  • Wie weit kann gerechnet werden?
  • statische Variablen werden stillschweigend auf Fehlwerte initialisiert, Blockvariablen nicht
  • checked { a = b + c; }
public class Program
{ static void Main( string[] args )
{ const int a = 1;
System.Console.WriteLine( a + 1 );
// Welchen Wert hat die Konstante "a" hier?
}}
Schreiben Sie in das folgende Programm an die Stelle von "/* ... */" einen Ausdruck, so daß der Wert der Konstanten "inch" die Länge einer Strecke in Zoll angibt, deren Zentimeterlänge durch den Zahlenwert in der Konstanten "cm" angegeben ist. Die ersten drei Zeilen und die letzte Zeile dürfen nicht verändert werden!
public class Program
{ static void Main( string[] args )
{ double lCm = 1.29; /* Laenge in cm (Zentimeter) */
double lInch = /* ... */;
System.Console.WriteLine( lInch ); /* Laenge in Zoll (ca 0,51 Zoll) */ }} public class Program
{ static void Main( string[] args )
{ double x = 1.;
double y = System.Math.Sin( x );
double z = System.Math.Sqrt( y );
double u = System.Math.Pow( y, 0.51 );
System.Console.WriteLine( z );
System.Console.WriteLine( u ); }} 0.9173172759781081
0.9157353176470164
Schreiben Sie die Übersetzungseinheit "Sinus1.cs" so um, daß dieselben Werte ausgegeben werden und dieselben Numerale und Funktionen zur Berechnung verwendet werden, aber keine Variablen mehr in dem Programm vorkommen. Ersetzen Sie zunächst die Variablen "x" überall durch ihre Definition, also durch den Wert "1.", und entfernen Sie die Definition der Variablen "x". Nach diesem Schema können dann alle anderen Definitionen eliminiert werden, bis nur noch die beiden Ausgabeausdrücke übrigbleiben.
public class Program
{ static void Main( string[] args )
{ System.Console.WriteLine( System.Math.Sin( 1. + System.Math.Log( 2.178 )));
System.Console.WriteLine( System.Math.Cos( 1. + System.Math.Log( 2.178 ))); }} 0.9785261962919047
-0.20612249554693626
Schreiben Sie die Einheit "Sinus2.cs" so um, daß derzeit wiederholt vorkommende gleiche Teilausdrücke nur einmal vorkommen. Definieren Sie diese dazu als Konstante und verwenden Sie die Konstante dann an deren Stellen. Verwenden Sie aber die in der Einheit "Sinus2.cs" vorkommenden Literale und Operatoren, ohne die Werte von Teilausdrücken dabei auszurechnen. Die Ausgabe des Programmes darf sich dadurch nicht ändern.
Zuweisung
Eine Variable ist eine Speicher, und ein Speicher kann geschrieben oder gelesen werden.
Die Leseoperation  wird durch Verwendung des Variablennamens als Argument oder Operand der meisten Operatoren ausgedrückt.
Die Schreiboperation  wird durch Verwendung des Variablennamens Operand spezieller Operatoren oder – unter Umständen – als Argument spezieller Funktionen ausgedrückt. Insbesondere durch Verwendung als linker Operand der Zuweisung »=«.
v = 2;
  • Erhöhen einer Variablen um 7?
  • Vertauschen zweier Variablen?
v = v
Links: Referenzkontext ⁻, rechts Wertkontext 
Konstantendeklarationen
Mit dem Schlüsselwort »const« können Übersetzungszeit-Konstanten gekennzeichnet werden.
public class MyClass { public const double PI = 3.14159; }
Der Modifizierer »const« impliziert »static« bei einer Klassenkonstante, daher ist eine Kombination nicht erlaubt.
Mit dem Schlüsselwort »readonly« können Nur-Lese-Variablen in Klassen gekennzeichnet werden.
Die Variablen in dem folgenden Block sind praktisch Konstanten, da sie nur einmal initialisiert und danach nicht mehr verändert werden. C♯  erlaubt es aber (im Gegensatz zu C++  oder Java ) nicht, solche Variablen als Konstanten zu kennzeichnen, also festzulegen, daß sie nach ihrer Initialisierung nicht mehr verändert werden können sollen.
{ double x = 1.; 
double y = System.Math.Sin( x );
double z = System.Math.Sqrt( y );
double u = System.Math.Pow( y, 0.51 );
System.Console.WriteLine( z );
System.Console.WriteLine( u ); }}
Parameterdeklarationen
public class Program
{ static void Main( string[] args )
{ { int zahl = 3; { System.Console.WriteLine( zahl ); }}
{ int zahl = 7; { System.Console.WriteLine( zahl ); }} }} 3
7 public class Program
{ public static void Ausgeben( int zahl )
{ System.Console.WriteLine( zahl ); } static void Main( string[] args )
{ Ausgeben( 3 );
Ausgeben( 7 ); }} 3
7
Der Parameter »zahl« ist effektiv konstant, da er nach seiner Initialisierung nicht mehr verändert wird, insbesondere wird er innerhalb seiner Methode nicht verändert. Leider erlaubt C♯  es nicht, ihn entsprechend zu kennzeichnen.
Parameternamen sollten klein geschrieben werden (camelCase  – nicht PascalCase ).
public class Program
{ int zahl; public static void Ausgeben( int zahl )
{ System.Console.WriteLine( zahl ); } static void Main( string[] args )
{ Ausgeben( 3 ); }} public class Program
{ public static void PaarAusgeben( int zahl, int zahl1 )
{ System.Console.Write( zahl );
System.Console.Write( ", " );
System.Console.WriteLine( zahl1 ); } static void Main( string[] args )
{ PaarAusgeben( 3 ); }}
Übung (entfällt bei Schnellkurs) Schreiben Sie eine Methode »Schreibzahl«, die eine als Argument beim Aufruf angegebene Zahl ausgibt!
Übung (entfällt bei Schnellkurs) Schreiben Sie eine Methode »Summe«, die die Summe der beiden als Argument angegebenen Zahlen ausgibt!
Übung Schreiben Sie ein möglichst kurzes Programm, das genau die folgende Ausgabe erzeugt.
    11910 
11910 32251
11910
23141
23141 32251
23141
10312
10312 32251
10312
24170
24170 32251
24170
17233
17233 32251
17233
24947
24947 32251
24947
Man kann ein sich wiederholendes Muster erkennen. Für dieses Muster soll einmal eine Methode mit einem Parameter deklariert werden, die dann wiederholt aufgerufen wird. Wenn man das richtig macht, findet sich dadurch jedes Numeral nur noch einmal im Quelltext, der dann auch relativ kurz ist.
Referenzparameter
class Program
{ static void Double( ref int x )
{ x = 2 * x; } static void Main()
{ int i = 12;
Double( ref i );
System.Console.WriteLine( i ); }}
Übung Methode zum Vertauschen zweier int-Variablen.
Überladung
Beispiel Methode zur Ausgabe des Typs (int, double).
Die leere Anweisung
Die einfachste Anweisung ist das Semikolon »;«. Die Ausführung dieser Anweisung bewirkt nichts.
Eigenschaftendeklarationen
class Example
{ static int x;
public int X
{ get { return x; }
set { x = value; }
}
Eigenschaften können beliebige Operationen im Gewande von Lese- und Schreiboperationen implementieren. Ihre Semantik sollte jedoch nicht zu überraschend sein. So wird es beispielsweise möglich, Prüfungen vor dem Schreiben vorzunehmen.
Klassen als Verbunde
zwei Zähler: jeweils inkrementieren und zurücksetzen, zunächst in einer Klasse, dann in zwei Klassen
Abstrakte Verbunde
Vorteile der Abstraktion: Implementation kann jederzeit ausgetauscht werden (vgl.: Austausch des Prozessors bei einem Computer, des Modells eines Autos)
Eintragszugriffsmodifizierer
Eintragszugriffsmodifizierer
»public« ohne Einschränkungen, PascalCase
»private« nur aus enthaltendem Typ, camelCase
Fehlen eines Eintragszugriffsmodifizierers wie »private« (bei »class«)
Dokumentation
Die Dokumentation ist ein unverzichtbarer Bestandteil jedes Programs, das nicht nur kurzfristig verwendet wird. Dennoch wird sie im folgenden zur besseren Übersichtlichkeit oft nicht aufgeführt.
Jede öffentliche Methode einer nicht nur kurzfristig verwendeten Klasse und die Klasse selber muß dokumentiert werden.
Die Dokumentation muß alles enthalten, was wichtig, um die dokumentierte Entität (Klasse oder Methode) richtig verwenden zu können, beispielsweise (bei einer Methode) alle nötigen Voraussetzungen des Aufrufs, alles was am Verhalten der Methode (Invarianten, Wirkungen und Werte) garantiert ist und wie dieses von den Parametern abhängt. Daneben kann das Verständnis durch Beispiele oder Kommentare erleichtert werden, die keine neuen Aussagen einführen, sondern die sonst gemachten Aussagen lediglich erläutern.
/// <summary>Class <c>Point</c> models a point in a two-dimensional
/// plane.</summary>
///
public class Point
{ ... /// <summary>method <c>draw</c> renders the point.</summary>
/// <remark>Uses polar coordinates</remark>
void draw() {...} /// <summary>This method changes the point's location to
/// the given coordinates.</summary>
/// <param name="xor">the new x-coordinate.</param>
/// <param name="yor">the new y-coordinate.</param>
public void Move( int xor, int yor )
{ X = xor; Y = yor; } /// <summary>Report a point's location as a string.</summary>
/// <returns>A string representing a point's location, in the form (x,y),
/// without any leading, trailing, or embedded whitespace.</returns>
public override string ToString()
{ return "(" + X + "," + Y + ")"; } int x; /// <value>Property <c>X</c> represents the point's x-coordinate.</value>
public int X
{
get { return x; }
set { x = value; }}}
Kontrakt (Schnittstelle) und Implementation
Der Kopf einer Methodendeklaration ist der Teil vor dem Block, der Rumpf ist der Block. In diesem Abschnitt wird unter einer abstrakten Methode  der Kopf zusammen mit der Dokumentation verstanden, also die Methode ohne ihren Rumpf.
Der Kontrakt (oder die Schnittstelle [nicht im engeren Sinne der Programmiersprache, sondern als allgemeiner Begriff]) einer abstrakten Methode ist der wesentliche Inhalt der Dokumentation zusammen mit dem Kopf der Methodendeklaration (vor dem Rumpf, also dem Block). Also alle in der Dokumentation gemachten Zusicherungen über die Methode. Nicht zum Kontrakt zählen Beispiele und Kommentare.
Die Dokumentation gibt im wesentlichen die „Semantik“ einer abstrakten Methode an, der Kopf die „Syntax“.
Eine Implementation einer abstrakten Methode ist der Rumpf (Block). Sie muß dafür sorgen, daß die Methode ihren Kontrakt erfüllt.
Ein Programmierer der eine Methode benutzen können will, soll lediglich den Kontrakt kennen müssen, nicht aber die Implementation.
Automatisierte Software-Test testen im wesentlichen, ob Systeme (Methoden) ihre Kontrakte auch korrekt implementieren. Damit dies möglich ist, muß ein System natürlich erst einmal einen schriftlichen Kontrakt haben.
Anwendungsbeispiel „Konto“ (Übungsaufgabe)
Schreiben Sie eine Klasse, die eine Konto modelliert, welches Einzahlen, Abheben und Saldoabfragen als jeweils eine Methode erlaubt.
Kontrakt Die Saldoabfrage eines Kontos muß die Summe aller Einzahlungen abzüglich der Summe aller Abhebungen ergeben.
Allgemeine Hinweise zu Übungsaufgaben
Bei der Beurteilung der Lösung einer Aufgabenstellung, wird es schwieriger, Lösungsteile zu erkennen und zu beurteilen, ob die Aufgabenstellung verstanden wurde, wenn der Autor von der Aufgabenstellung abweicht. Daher sollte die Aufgabenstellung zunächst möglichst genau beachtet werden. Ist eine Abweichung gewünscht, so kann diese als eine zusätzliche  Variante neben der genaue Lösung angelegt werden.
Falls das Einhalten der folgenden Regeln jedoch so schwer fällt, daß die Aufgabe dann nicht gelöst werden kann, ist es besser doch von diesen Regeln abzuweichen als gar keine Lösung zu schreiben.
Ergänzende Themen Der ternäre Operator (»?« und »:«)
static int M( int i ){ return i != 0 ? 10/i : 0; }
Welchen Wert haben »M( 2 )« und »M( 0 )«?
Ergänzende Themen Logische Operatoren
&, |, &&, ||

if( Counter.IsInvalid() | Counter.Value == 0 )return;

if( Counter.IsInvalid() || Counter.Value == 0 )return;

if( Counter.IsValid() && Counter.Value > 0 )...
Ergänzende Themen »if«
if( a )System.Console.WriteLine( "A" ); else System.Console.WriteLine( "B" );
Vermeiden der Wiederholung von »System.Console.WriteLine«?
Ergänzende Themen Schleifen
»while«, »do«, »for«
Ergänzende Themen »switch«
int v = 1;
switch( v )
{ case 1:
System.Console.WriteLine( "Fall 1" );
break; case 2:
System.Console.WriteLine( "Fall 2" );
break; default:
Console.WriteLine("Fehlfall");
break; }
(const-Konstante ist als Marke erlaubt, kein „Durchfallen“ zulässig)
Ergänzende Themen Spezielle Zuweisungen
{ int i = 12; i += 7; }

{ int i = 12; i *= 7.0; i = i * 7.0; }

{ int i = 12;
System.Console.WriteLine( ++i );
System.Console.WriteLine( i++ ); }
Übungsaufgabe Auto
Schreiben Sie eine Klasse »Auto«, welche ein Auto modelliert. In diesem einfachen Modell soll ein Auto lediglich durch seine Höchstgeschwindigkeit charakterisiert werden. Je nach dem Land wird die Geschwindigkeit jedoch entweder in Stundenkilometer (km/h) oder in “miles per hour” (mph) angegeben. Daher soll die Klasse vier Methoden haben:
Motivation Für einen Handesplatz sollen Hersteller aus den Vereinigten Staaten von Nordamerika und aus der Bundesrepublik Deutschland die Höchstgeschwindigkeit in der ihnen vertrauten Einheit festlegen können und Kunden sollen sie in der ihnen vertrauten Einheit lesen können.
Kontrakt 0: Der Aufruf der Get-Methode »GetKmh« wird durch den Wert des Arguments der zuletzt aufgerufenen Set-Methode (»SetMph« oder »SetKmh«) bestimmt. Falls zuletzt »SetKmh« aufgerufen wurde, ist der Wert der Get-Methode der Wert des Arguments von »SetKmh«. Falls zuletzt »SetMph« aufgerufen wurde ist der Wert der Get-Methode der Wert des in km/h umgerechneten Arguments dieses letzten Aufrufs von »SetMph«, welches als Geschwindigkeit in mph interpretiert wird. 1: Der Aufruf der Get-Methode »GetMph« wird durch den Wert des Arguments der zuletzt aufgerufenen Set-Methode (»SetMph« oder »SetKmh«) bestimmt. Falls zuletzt »SetMph« aufgerufen wurde, ist der Wert der Get-Methode der Wert des Arguments von »SetMph«. Falls zuletzt »SetKmh« aufgerufen wurde ist der Wert der Get-Methode der Wert des in mph umgerechneten Arguments dieses letzten Aufrufs von »SetKmh«, welches als Geschwindigkeit in kmh interpretiert wird.
Anstatt vierer Methoden darf die Aufgabe auch mit zwei C♯ -Eigenschaften „Kmh“ und „Mph“ gelöst werden. (Auch wenn dies nicht geschieht, implementieren die ersten und zweiten Methodenpaare jeweils eine Eigenschaft des Verbunds im allgemeinen Sinne des Wortes „Eigenschaft“.)
Zur Nachbesprechung Was kann man an diesem Beispiel über das Verhältnis zwischen Eigenschaften und Feldern erkennen? Was sind „Getter“ und „Setter“ und warum werden sie kritisiert?
Übungsaufgabe Test
Einführung Als Test  wird hier ein Software-Test verstanden, der automatisch ermittelt, ob eine Abweichung einer Implementation vom Kontrakt gefunden wurde. Das Ausprobieren einer Klasse durch einzelne Aufrufe, bei denen der Programmierer selber das Verhalten mit dem Kontrakt vergleicht, wird hier im Gegensatz dazu als „Ausprobieren“ bezeichnet. Abgesehen von ganz wenigen Ausnahmen kann man durch Tests nie „beweisen“, daß ein Kontrakt korrekt implementiert wurde – es geht nur darum, so viele Fehler wie möglich zu finden. (Unterhaltsame Lektüre über Tests: “They write the right stuff ” »http://www.fastcompany.com/node/28121/print«. “Our requirements are almost pseudo-code[.] ”)
Schreiben Sie einen Test der Klasse »Auto« in der Methode »Main« der Programm-Klasse. Der Test soll an Hand einiger weniger Aufrufe untersuchen, ob die Methoden den Kontrakt implementieren. Da es natürlich nicht möglich ist, alle möglichen Kombinationen von Aufrufen und double-Werten durchzuprobieren genügen einige wenige exemplarische Aufrufe.
Die Testmethode »Main« soll »Test nicht bestanden.« ausgeben, wenn eine Abweichung vom Kontrakt gefunden wurde, und andernfalls nichts.
Zusatzaufgabe Durch Darstellungseffekte könne double-Werte etwas „verfälscht“ werden, der Kontrakt soll aber noch als erfüllt gelten, wenn der Wert eines Methodenaufrufs vom mathematisch korrekten Wert abweicht, falls diese Abweichung so klein ist, daß sie in der Praxis nicht stören würde.
Übungsaufgabe zu Softwaretests, Teil 0
Schreiben Sie eine Klasse »Programm« mit einer Methode »Main« zum Testen einer anderen Klasse »Schalter«. Schreiben Sie möglichst noch keine  Implementation der Klasse »Schalter«. (Damit kann die Klasse »Programm« zunächst noch nicht ausgeführt werden.)
Stellen Sie sich eine Klasse »Schalter« vor, die einen Schalter mit den parameterlosen und wertfreien Wirkmethoden »Einschalten« und »Ausschalten« und der parameterlosen und wirkungslosen bool-Wertmethode »An« hat.
Kontrakt Der Wert des Aufrufs »An()« ist wahr genau dann, wenn während des Ablaufs des Programms die Wirkmethode »Einschalten« schon einmal aufgerufen wurde und die zuletzt davor aufgerufene Wirkmethode des Schalters »Einschalten()« war.
Die Testmethode »Main« soll die Methode »An()« (einmal oder mehrere Male) aufrufen und »Test nicht bestanden.« ausgeben, wenn »An()« mindestens einmal eine Wert hat, der mit dem Kontrakt nicht vereinbar ist; andernfalls sollte das Testprogramm nichts ausgeben.
Übungsaufgabe zu Softwaretests, Teil 1
Schreiben Sie eine Klasse »Schalter« mit den drei zuvor genannten Methoden. Diese Methoden sollen aber nur „Blindmethoden“ sein, die also nicht  den Kontrakt umsetzen sollen, sondern eine möglichst kurze einfache Implementation haben. Beispielsweise könnte die Methode »An()« immer den Wert »true« zurückgeben. (Das Testprogramm sollte nun ausgeben »Test nicht bestanden.«.)
Übungsaufgabe zu Softwaretests, Teil 2
Ändern Sie die Implementation der Klasse »Schalter« nun so ab, daß die Methoden den Kontrakt erfüllen. (Hierbei kann man beobachten, wie der Kontrakt indirekt festlegt ob die Klasse Variablen braucht, was aber nicht immer eindeutig bestimmt sein muß.) (Das Testprogramm sollte nun nichts ausgeben.)
Übungsaufgabe zu Softwaretests, Teil 3
Ändern Sie die Implementation der Klasse »Schalter« nun so ab, daß die Klasse zwar den Test besteht, aber den Kontrakt trotzdem nicht erfüllt.

Anhang

>722315C♯ -Aufbaukurs
>722316 Fortgeschrittene Themen der C♯ -Programmierung
>722318C♯ -Wunschthemen
>722317 Anhang

Beispiel
Erklärung
Übung

Seiteninformationen und Impressum   |   Mitteilungsformular  |   "ram@zedat.fu-berlin.de" (ohne die Anführungszeichen) ist die Netzpostadresse von Stefan Ram.   |   Eine Verbindung zur Stefan-Ram-Startseite befindet sich oben auf dieser Seite hinter dem Text "Stefan Ram".)  |   Der Urheber dieses Textes ist Stefan Ram. Alle Rechte sind vorbehalten. Diese Seite ist eine Veröffentlichung von Stefan Ram. Schlüsselwörter zu dieser Seite/relevant keywords describing this page: Stefan Ram Berlin slrprd slrprd stefanramberlin spellched stefanram723208 stefan_ram:723208 Erster C#-Kurs Stefan Ram, Berlin, and, or, near, uni, online, slrprd, slrprdqxx, slrprddoc, slrprd723208, slrprddef723208, PbclevtugFgrsnaEnz Erklärung, Beschreibung, Info, Information, Hinweis,

Der Urheber dieses Textes ist Stefan Ram. Alle Rechte sind vorbehalten. Diese Seite ist eine Veröffentlichung von Stefan Ram.
https://www.purl.org/stefan_ram/pub/erster_kurs_csharp