Ergänzungen zu C♯
Hinweis für den Dozenten ► Falls hier noch Zeit für Ergänzungen ist, so können auch die Java-Lektionen herangezogen werden, da deren Beispielprogramme meist relativ schnell nach C# übersetzt werden können.
Vergleiche
!=
<
>
<=
>=
- 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«
- Zuweisend »x=y«
/ Überprüfung eines Ergebnisses
Schreiben Sie ein Programm, welches überprüft, ob eine von »global::Microsoft.JScript.MathObject.random« gelieferte Zufallszahl wirklich im Bereich von 0 (einschließlich) bis 1 (ausschließlich) liegt, indem Sie dabei folgendermaßen vorgehen: Rufen Sie eine solche Zufallszahl ab und geben Sie das Wort »Fehler!« aus, falls diese sich nicht in jenem Bereich befindet.
»+=««, »-=«, »*=«, »/=«, – Verbundzuweisungen
- Spezielle Zuweisungen
{ int i = 12; i += 7; } { int i = 12; i *= 7.0; i = i * 7.0; } { int i = 12;
global::System.Console.WriteLine( ++i );
global::System.Console.WriteLine( i++ ); }
»++«, »--« – Inkrementieren und Dekrementieren
»;« – Die leere Anweisung
- Die leere Anweisung
- Die einfachste Anweisung ist das Semikolon »;«. Die Ausführung dieser Anweisung bewirkt nichts.
»&&«, »||«, »!« – Logische Operatoren
- Logische Operatoren
&, |, &&, || if( Counter.IsInvalid() | Counter.Value == 0 )return; if( Counter.IsInvalid() || Counter.Value == 0 )return; if( Counter.IsValid() && Counter.Value > 0 )...
- 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 )«
»[]« – Reihungen (arrays)
- Einstiegspunkte
- Für ein Programm sind die folgenden vier Einstiegspunkte möglich.
public static void Main() {…} public static void Main(string[] args) {…} public static int Main() {…} public static int Main(string[] args) {…}
- (Quelle: ECMA-334, 4th edition, 10. Basic concepts, 10.1 Application startup)
- Eindimensionale Reihungen (gefaltet)
- int[] a = new int[ 3 ]{ 1, 2, 3 };
int[] a = new int[ 3 ]; // drei Zeilen unbestimmter Länge
a[ 0 ]= 1;
Mehrdimensionale Reihungen (gefaltet) - Der Speicher erscheint aus Sicht des Prozessors als eindimensional (beziehungsweise er hat vielleicht ein mehrdimensionale Struktur, die aber beim Programmieren kaum ausgenutzt werden kann, da sie nicht veränderlich ist). Eine eindimensionale Struktur kann jedoch wie bei einer gedanklichen Faltung als mehrdimensional interpretiert werden, indem jeweils die ersten Einträge als „erste Zeile“ angesehen werden, die nächsten als „zweite Zeile“ und so weiter.
- Im Rest dieses Textes beschränken wir uns der Einfachheit halber auf zweidimensionale Reihungen, aber die Aussagen können jeweils auch auf Reihungen mit noch mehr Dimensionen übertragen werden.
- Initialisierung einer Variablen mit einer Referenz auf ein neu angelegtes Reihungsobjekt
int[ , ]a = new int[ 4, 2 ];
- Nicht möglich, ist eine Schreibweise wie die folgende (»[ 4, 2 ]« auf der linken Seite).
int[ 4, 2 ]a = new int[ 4, 2 ];
- Bei Angabe der Inhalte kann der Compiler die Dimensionen der Reihung selber ableiten.
int[ , ]a1 = new int[ , ]{{ 1, 2 },{ 3, 4},{ 5, 6 },{ 7,8 }};
- Die folgende Kurzschreibweise zur Angabe des Inhalts einer Reihung kann nur in Initialisierungen verwendet werden.
int[ , ]a2 ={{ 1, 2 },{ 3, 4 },{ 5, 6 },{ 7, 8 }};
- Die Zugriffe erfolgen entsprechend wie bei eindimensionalen Reihungen. Im folgenden Ausdruck sieht man links einen schreibenden und rechts einen lesenden Zugriff.
a[ 2, 1 ]= a[ 3, 4 ]+ 12
- Um die Zahl der Einträge in einer Dimension zu erhalten, wird diese als Argument (0, 1, …) angegeben
height = a.GetUpperBound( 0 )+ 1;
height = a.GetLength( 0 ); width = a.GetUpperBound( 1 )+ 1;
width = a.GetLength( 1 );- Aber auch die Anzahl aller Einträge steht zur Verfügung
totalsize = array0.Length;
- Übung Summenprozent.
- Mehrdimensionale Reihungen (linksbündig, ragged )
- Bei einer gefalteten Reihung haben alle „Unterreihungen“ dieselbe Größe. Manchmal werden Listen von unterschiedliche langen Zeilen benötigt. In diesem Fall kann eine eindimensionale Reihung angelegt werden, die jeweils Referenzen auf weitere eindimensionale Reihungen (Zeilen): Eine „Reihung von Reihungen“.
- Reihung von (Referenzen auf )Reihungen
int[][] a = new int[ 3 ][]; // drei Zeilen unbestimmter Länge
a[ 0 ]= new int[]{ 1, 2, 3 }; // erste Zeile
a[ 1 ]= new int[]{ 4 }; // zweite Zeile
a[ 2 ]= new int[]{ 5, 6 }; // dritte Zeile- Anschauliche Darstellung der obigen Reihung »a«
1 2 3
4
5 6- Verschachtelte Schleife zum Durchlaufen der Einträge
for( int i = 0; i < a.GetLength( 0 ); ++i )
for( int j = 0; j < a[ i ].GetLength( 0 ); ++j )…- Verschachtelte Schleife zum Durchlaufen der Einträge (Variante)
foreach( int[] b in a )for( int s in b )…
- Übungsfrage Wie könnte eine 100×100-Reihung von insgesamt 10000 Schriftzeichen, die nur Doppelpunkte enthalten soll, als linksbündige Reihung besonders speicherplatzsparend eingerichtet werden (so daß sie insgesamt deutlich weniger Speicherplatz benötigt als die entsprechende gefaltete Reihung)?
»using« – Importdeklarationen
Deklaration statischer Klassenkonstanten
Die Überladung von Methodennamen
- Überladung
- Beispiel Methode zur Ausgabe des Typs (int, double).
Der cast -Operator
- 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 )«?.
»char« – Einzelne Schriftzeichen
»'A' + 'A'« hat zunächst Aufbau »char + char«, nach Wandlung dann »int + int«
- Beispiel:
System.Console.WriteLine( 65 );
System.Console.WriteLine( 'A' );
System.Console.WriteLine( ( char )65 );
System.Console.WriteLine( ( char )'A' );- Übung In einem Programm soll eine zweidimensionale Reihung aus acht Zeilen und acht Spalten vom Datentyp »char« angelegt werden. Dieses „Schachbrett“ soll überall Doppelpunkte »:« enthalten, nur in der Diagonalen (von der Position (0,0) zur Position (7,7)) sollen Nummernzeichen »#« enthalten sein. Das Schachbrett soll, nachdem es so eingerichtet wurde, dann ausgegeben werden.
#:::::::
:#::::::
::#:::::
:::#::::
::::#:::
:::::#::
::::::#:
:::::::#- Zusatzaufgabe Falls Sie bei der Lösung verschachtelte Schleifen verwendet haben sollten: Welche Art der Verschachtelung von Schleifen ist eventuell effizienter? Können Sie dies nachmessen? Können Sie auch eine Lösung schreiben, die nur Schleifen verwendet, welche nicht verschachtelt sind (auch Aufrufe einer weiteren Methode mit einer weiteren Schleife gelten als „Verschachtelung“)?
- Zeichenliterale und Zeichenwerte
- »Z«; »'Z'«
- Steuersequenzen, char=System.Char.
- Überladung von Methodennamen: WriteLine(Char)
»%« – Der Divisionsrest
- Divisionrest
- Für numerische Ausdrücke »x« und »y« ist »x % y« der Rest der Division von »x« durch »y«.
»for« – Die for -Schleife
»else« – Die Ausführungswahl
»switch« – Die Mehrfachauswahl
- Ergänzende Themen »switch«
int v = 1;
switch( v )
{ case 1:
global::System.Console.WriteLine( "Fall 1" );
break; case 2:
global::System.Console.WriteLine( "Fall 2" );
break; default:
global::System.Console.WriteLine("Fehlfall");
break; }- (const-Konstante ist als Marke erlaubt, kein „Durchfallen“ zulässig)
Mehr über String-Literale
Mehr über Gleitkommaarithmetik
Statische Klassen
- Klassendeklarationen
- PascalCase für Klassennamen
static class AufEinemBaumEinKuckuckSass
{
public static void RefrainAusgeben()
{ global::System.Console.WriteLine("Sim sa la dim, bam ba,");
global::System.Console.WriteLine("Sa la du, sa la dim -"); } public static void Ausgeben()
{ { global::System.Console.WriteLine("Auf einem Baum ein Kuckuck, -");
RefrainAusgeben();
global::System.Console.WriteLine("Auf einem Baum ein Kuckuck sass."); } { global::System.Console.WriteLine("Da kam ein junger Jaeger, -");
RefrainAusgeben();
global::System.Console.WriteLine("Da kam ein junger Jaegersmann."); } { global::System.Console.WriteLine("Der schoss den armen Kuckuck, -");
RefrainAusgeben();
global::System.Console.WriteLine("Der schoss den armen Kuckuck tot."); }}}
static class Vogelhochzeit
{ public static void RefrainAusgeben()
{ global::System.Console.WriteLine("Fi-di-ra-la-la, fi-di-ra-la-la, fi-di-ra-la-la-la-la!"); } public static void Ausgeben()
{ global::System.Console.WriteLine("Ein Vogel wollte Hochzeit machen, in dem gruenen Walde.");
RefrainAusgeben();
global::System.Console.WriteLine("Die Drossel war der Braeutigam, die Amsel war die Braute.");
RefrainAusgeben();
global::System.Console.WriteLine("Die Lerche, die Lerche, die fuehrt die Braut zur Kerche.");
RefrainAusgeben(); }}
public static class Program
{ public static void Main()
{ AufEinemBaumEinKuckuckSass.Ausgeben();
Vogelhochzeit.Ausgeben(); }}- 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 = global::System.Math.Sin( x );
double z = global::System.Math.Sqrt( y );
double u = global::System.Math.Pow( y, 0.51 );
global::System.Console.WriteLine( z );
global::System.Console.WriteLine( u ); }}- Ü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.
- Ü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.
SetKmh
Diese wertfreie Wirkmethode mit einem double-Parameter erlaubt es, die Höchstgeschwindigkeit festzulegen, dabei wird der Argumentwert in der Einheit „km/h“ angegeben.GetKmh
Diese wirkungsfreie Wertmethode ohne Parameter erlaubt es, die zuletzt festgelege Höchstgeschwindigkeit zu ermitteln. Der Wert des Aufrufs dieser Methode ist in der Einheit „km/h“ zu verstehen.SetMph
Diese wertfreie Wirkmethode mit einem double-Parameter erlaubt es, die Höchstgeschwindigkeit festzulegen, dabei wird der Argumentwert in der Einheit „mph“ angegeben.GetMph
Diese wirkungsfreie Wertmethode ohne Parameter erlaubt es, die zuletzt festgelege Höchstgeschwindigkeit zu ermitteln. Der Wert des Aufrufs dieser Methode ist in der Einheit „mph“ zu verstehen.
- 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?
Getrennte Übersetzung
Objektorientierte Programmierung
Nichtstatische Aufrufe
Strukturobjekte und ihre Felder
- 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)
Strukturobjekte und ihre Methoden
- Deklarieren Sie in dem folgenden Programm an der Stelle der Lücke »…« eine nicht-statische Methode »getX()«, welche den Wert des Feldes »x« zurückgibt!
- Deklarieren Sie in dem folgenden Programm an der Stelle der Lücke »…« eine nicht-statische Methode »setX(int)«, welche den Wert des Feldes »x« als Wert des Arguments des Aufrufs von »setX(int)« festlegt!
- Deklarieren Sie in dem folgenden Programm an der Lücke »…« eine nicht-statische Methode »addToX(int)«, welche den Wert des Arguments ihres Aufrufs zum Werte des Feldes »x« hinzuaddiert!
- Schreiben Sie eine Klasse so, daß die dann parameterlose Methode »average()« den Mittelwert der beiden zuvor mit den nichtstatischen Methoden »setX(int)« und »setY(int)« festgelegten Werte ergibt.
- Deklarieren eine Methode »value()« für Objekte, die zählen, wie oft ihre Methode »count()« zuvor aufgerufen wurde.
Objekte und ihre Eigenschaften
- Eigenschaftendeklarationen
public 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.
Hüllklassen
Delegate
Annotationen
Assertationen
instanceof
casts
Exceptions
Konstruktoren
private und Invarianten
- Eintragszugriffsmodifizierer
- Eintragszugriffsmodifizierer
- »public« ohne Einschränkungen, PascalCase
- »private« nur aus enthaltendem Typ, camelCase
- Fehlen eines Eintragszugriffsmodifizierers wie »private« (bei »class«)
Erweitern von Klassen (Vererbung)
Ersetzen von Methoden bei der Erweiterung
Einlesen von der Konsole
Dateizugriffe
Behälter
Beispiel
Erklärung
Übung
Anmerkung
Die Operatoren »>>« und »>>=« bestehen aus jeweils zwei lexikalischen Einheiten »>« »>« beziehungsweise »>« »>=« zwischen die aber jeweils kein Leerraum geschrieben werden darf.