Arbeiten mit .NET: C-Sharp/ Grundlagen/ Der Aufbau eines Programms/ Die Main-Methode

Aus Wikibooks
Zur Navigation springen Zur Suche springen

Die Main-Methode ist der Einstiegspunkt jedes .NET-Programms.

Allgemeine Bedeutung[Bearbeiten]

Beim Start eines Programms muss feststehen, wo und wie es seine Arbeit beginnen soll. Unter .NET ist dafür (wie schon unter C) eine Methode namens Main vorgesehen.

Attention green.svg

Merke
  • Jedes .NET-Programm beginnt mit der Main-Methode als "Einstiegspunkt" des Programms.
  • Innerhalb einer Anwendung gibt es genau einen solchen Einstiegspunkt.
  • Für eine Klassenbibliothek und für Windows-Dienste (Services) ist kein Einstiegspunkt vorgesehen.

Grundsätzlich darf es nur eine Main-Methode in einer Anwendung geben, und diese muss direkt zur Verfügung stehen (d.h. ohne dass eine Instanz einer Klasse erzeugt werden muss). Wie dies geregelt wird, hängt von der Arbeitssituation (siehe die folgenden Abschnitte) und der Programmiersprache ab. In der Praxis ist sie sehr oft in einer Program-Klasse enthalten.

Wenn es ausnahmsweise in mehreren Klassen eine solche Methode gibt, kann und muss dem Compiler durch eine Option mitgeteilt werden, welche als Einstiegspunkt gelten soll. Vermeiden Sie besser solche Unklarheiten.

Varianten[Bearbeiten]

Je nach Notwendigkeit stehen verschiedene Möglichkeiten für die Main-Methode zur Verfügung.

Die einfache Version[Bearbeiten]

Im einfachsten Fall wird eine Methode ohne Argumente und Rückgabewert vorgesehen:

C#-Quelltext
static void Main()
{
  // hier steht die Steuerung des Arbeitsablaufs
}
Delphi.Prism-Quelltext
class method Program.Main();
begin
  // hier steht die Steuerung des Arbeitsablaufs
end;
VB.NET-Quelltext
Sub Main()
  ' hier steht die Steuerung des Arbeitsablaufs
End Sub

Das Programm wird gestartet, erledigt eine Aufgabe und wird beendet, ohne dass der Benutzer, der das Programm gestartet, anschließend ein Ergebnis erhält. Dies ist vor allem bei Windows-Anwendungen der übliche Weg, aber nicht der einzig mögliche.

Mit Rückgabewert[Bearbeiten]

Main kann auch als Methode mit einem Integer als Rückgabewert deklariert werden. Dies ist vor allem als Fehlercode gedacht (siehe unten unter "Mit Argumenten und Rückgabewert").

Der folgende Code liefert als Ergebnis die Anzahl der logischen Laufwerke (einschließlich aller Partitionen):

C#-Quelltext
static int Main()
{
	int result = System.IO.Directory.GetLogicalDrives().Length;
	if (result < 3)
		Console.WriteLine("wenige Laufwerke");
	else
		Console.WriteLine("mehr Laufwerke");
	Console.ReadKey(true);
	return result;
}
Delphi.Prism-Quelltext
class method Program.Main(): Integer;
var numberOfDrives: Integer;
begin
	numberOfDrives := System.IO.Directory.GetLogicalDrives().Length;
	if (numberOfDrives < 3) then
		Console.WriteLine('wenige Laufwerke')
	else
		Console.WriteLine('mehr Laufwerke');
	Console.ReadKey(true);
	exit numberOfDrives;
end;
VB.NET-Quelltext
Private Shared Function Main() As Integer
	Dim result As Integer = System.IO.Directory.GetLogicalDrives().Length
	If result < 3 Then
		Console.WriteLine("wenige Laufwerke")
	Else
		Console.WriteLine("mehr Laufwerke")
	End If
	Console.ReadKey(True)
	Return result
End Function

In diesem Fall wird der gesuchte Wert zuerst einer Variablen zugewiesen, damit er über if ausgewertet werden kann; erst am Schluss wird er bei return bzw. exit als Ergebnis festgelegt.

Hinweis: Ein solches Verfahren ist nur dann sinnvoll, wenn das "aufrufende" Programm ein solches Ergebnis auch abfragt und prüft.

Nuvola apps important.svg Für jeden möglichen Programmablauf muss ein Rückgabewert festgelegt werden. Es empfiehlt sich (wie im übernächsten Beispiel), den Rückgabewert immer als letzten Befehl in der Main-Methode festzulegen – ggf. mit dem Standardwert 0.

Mit Argumenten[Bearbeiten]

Das Argument args enthält in einem String-Array Werte, die dem Programm beim Start mitgegeben werden. Damit kann der Programmablauf bereits beim Start beeinflusst werden. Wir ändern dazu unser Einstiegsprogramm "Mein neues Auto".

Bei dieser Variante werden die Mindestangaben (Typ, Motor, ID) beim Programmstart vorgegeben und übernommen.

C#-Quelltext
static void Main(string[] args)
{
	string cartype, motortype;
	int nextid;
	if(args.Length < 3) 
	{
		// wenn Werte fehlen, dann Programm mit Meldung abbrechen
		Console.WriteLine("Angaben fehlen, Programm bricht ab.");
		Console.Write("Press any key to continue . . . ");
		Console.ReadKey(true);
		return;
	} 
	else
	{
		cartype = args[0];
		motortype = args[1];
		nextid = int.Parse(args[2]);
	}
 
	// Fahrzeug erstellen mit diesen Angaben
	Car mycar = new Car(cartype, motortype, nextid);
	Console.Write("Press any key to continue . . . ");
	Console.ReadKey(true);
}
Delphi.Prism-Quelltext
class method Program.Main(Args: array of String);
var cartype, motortype: string;
    nextid: Integer;
    mycar: Car;
begin
	if Length(Args) < 3
	then begin
		// wenn Werte fehlen, dann Programm mit Meldung abbrechen
		Console.WriteLine('Angaben fehlen, Programm bricht ab.');
		Console.Write('Press any key to continue . . . ');
		Console.ReadKey(true);
		exit;
	end
	else begin
		cartype := args[0];
		motortype := args[1];
		nextid := Integer.Parse(args[2]);
	end;
 
	// Fahrzeug erstellen mit diesen Angaben
	mycar := new Car(cartype, motortype, nextid);
	Console.WriteLine(mycar.ToString());
	Console.Write('Press any key to continue . . . ');
	Console.ReadKey(true);
end;
VB.NET-Quelltext
Private Shared Sub Main(args As String())
	Dim cartype As String, motortype As String
	Dim nextid As Integer
	If args.Length < 3 Then
		' wenn Werte fehlen, dann Programm mit Meldung abbrechen
		Console.WriteLine("Angaben fehlen, Programm bricht ab.")
		Console.Write("Press any key to continue . . . ")
		Console.ReadKey(True)
		Return
	Else
		cartype = args(0)
		motortype = args(1)
		nextid = Integer.Parse(args(2))
	End If

	' Fahrzeug erstellen mit diesen Angaben
	Dim mycar As New Car(cartype, motortype, nextid)
	Console.WriteLine(mycar.ToString())

	Console.Write("Press any key to continue . . . ")
	Console.ReadKey(True)
End Sub

Das Programm erwartet ein Array mit mindestens drei Strings; wenn etwas fehlt, bricht das Programm mit einer Fehlermeldung ab. Andernfalls werden die Werte in Variable übernommen: der erste String als Car-Typ, der zweite als Motor-Typ und der dritte als ID. Da ID eine Zahl ist, muss der String in einen Integer konvertiert werden. (Bitte beachten Sie, dass falsche Festlegungen noch nicht geprüft werden.) Mit den auf diese Weise bestimmten Werten wird das Auto erzeugt.

In der IDE können diese Start-Argumente vorgegeben werden über Projekt > Optionen > Debuggen > Start-Optionen > Kommandozeilen-Argumente. Mit Leerzeichen werden einzelne Argumente getrennt; wenn (wie hier) auch Leerzeichen Teil eines Strings sind, müssen sie mit Anführungszeichen verbunden werden:

AN3 "998cm³ 44kW" 416

Der erste Teil "AN3" wird als Typ verstanden, der zweite innerhalb der Gänsefüßchen als Motor und der dritte Teil als ID.

Dieses Verfahren ist nützlich, wenn z.B. im Explorer eine Datei zur Bearbeitung ausgewählt wird, wenn ein Programm je nach Vorgabe unterschiedliche Aufgaben automatisch erledigen soll oder wenn die Konzeption eines Programms vorbestimmt wird. In allen Fällen geht es darum, das Programm automatisch – ohne Zutun des Benutzers – zu steuern.

Mit Argumenten und Rückgabewert[Bearbeiten]

Beide Varianten können auch verbunden werden. Für das Beispiel "Mit Argumenten" kann die Fehlermeldung durch diesen Fehlercode ersetzt werden:

C#-Quelltext
static int Main(string[] args)
{
	if(args.Length < 3) 
	{
		// wenn Werte fehlen, dann mit Fehlercode 1 abbrechen
		return 1;
	} 
	else  
	// usw. bis zum Ende
	return 0;
}
Delphi.Prism-Quelltext
class method Program.Main(Args: array of String): Integer;
begin
	if Length(Args) < 3
	then begin
		// wenn Werte fehlen, dann mit Fehlercode 1 abbrechen
		exit 1;
	end
	// usw. bis zum Ende
	exit 0;
end;
VB.NET-Quelltext
Private Shared Function Main(args As String()) As Integer
	If args.Length < 3 Then
          Return 1
	Else
	  ' usw. bis zum Ende
          Return 0
        End If
End Sub

In diesem Beispiel wird das Programm im Fehlerfall sofort abgebrochen mit dem Rückgabewert 1, der als Fehlercode interpretiert werden kann. Andernfalls wird der normale Ablauf fortgesetzt; schließlich wird das Programm mit dem Rückgabewert 0 beendet, was als "Ende ohne Problem" zu verstehen ist.

Weitere Hinweise[Bearbeiten]

Die Inhalte von Main[Bearbeiten]

Grundsätzlich gilt:

  • Die Main-Methode steuert die gesamte Funktionalität der Anwendung. Das Programm fängt mit der ersten Befehlszeile an; nach Erledigung der letzten Befehlszeile ist das Programm beendet.
  • Eine Konsolenanwendung enthält grundsätzlich die gesamte Funktionalität. Bestandteile werden nur deshalb in eigene Klassen und Methoden ausgelagert, um die Anwendung übersichtlich zu gestalten und besser zu strukturieren.
  • Für eine Windows-Anwendung gilt das prinzipiell genauso. Aber die Hauptarbeit wird vom Hauptformular aus gesteuert; die Main-Methode kümmert sich um Vorarbeiten und (äußerst selten) um Abschlussarbeiten.

Die folgenden Aufgaben, die durch die Main-Methode ausgelöst oder erledigt werden, beziehen sich deshalb in erster Linie auf Windows-Anwendungen.

  • Es kann geprüft werden, ob eine Anwendung überhaupt gestartet werden darf oder nicht. Beschränkungen durch Nutzungsdauer, Anzahl der offenen Instanzen usw. werden geprüft; im Falle eines Falles wird das Programm sofort beendet.
  • Übergebene Argumente werden analysiert. Abhängig von deren Inhalt wird ein bestimmtes Formular als Hauptformular geöffnet, eine bestimmte Datei geladen oder ein spezieller Arbeitsablauf ausgelöst.
  • Ein Startbildschirm wird angezeigt, während umfangreiche Vorarbeiten stattfinden, und vor dem Start des Hauptformulars gelöscht.
  • Über ein Login-Formular werden Benutzername und Passwort geprüft und davon bestimmte Zugangsrechte abhängig gemacht.

All diese Situationen werden in den Büchern über Windows-Forms sowie WPF und Silverlight behandelt.

Besonderheiten[Bearbeiten]

Bei einer Programmiersprache sind u.U. spezielle Bedingungen zu beachten.

Für Visual Basic
  • Für WinForms-Anwendungen muss keine Main-Methode (weder als Funktion noch als Prozedur) vorhanden sein. Bei Bedarf erzeugt der Compiler selbst eine.
  • VB unterscheidet bei der Art der Methoden:
    • Main ist als Sub zu deklarieren, wenn ohne Rückgabewert gearbeitet wird.
    • Es ist dagegen als Function zu benutzen, wenn mit Rückgabewert gearbeitet wird.
Für Delphi.Prism

Als Argument kann statt eines String-Arrays auch ein einzelner String verwendet werden.

Zusammenfassung[Bearbeiten]

Ohne die Main-Methode kann ein Programm nicht funktionieren. Sie kann mit oder ohne Argumente ablaufen, und sie kann bei Bedarf einen Rückgabewert als Ergebnis des Programms festlegen.

Übungen[Bearbeiten]

Übung 1 Definitionen Zur Lösung

Welche der folgenden Aussagen sind wahr, welche sind falsch?

  1. Jede Anwendung benötigt mindestens eine Main-Methode für den Start der Anwendung.
  2. Eine Anwendung kann mehrere Main-Methoden enthalten.
  3. Wenn mehrere Methoden enthalten sind, wird diejenige in der Program-Klasse für den Start benutzt.
  4. Für den Start muss eine Instanz der Program-Klasse erzeugt werden, danach kann die Main-Methode ausgeführt werden.
  5. Die Main-Methode kann mit oder ohne Argumente deklariert werden.
  6. Als Argument kann ein Integer- oder ein String-Wert übergeben werden.
  7. Das Arbeitsergebnis wird als Integer-Wert zurückgegeben.

Übung 2 Argumente Zur Lösung

Skizzieren Sie in "Pseudo-Code" eine Main-Methode für folgende Aufgabe: Das Programm erhält einen Dateinamen als Argument. Wenn der Dateiname fehlt, soll er per Console abgefragt werden. Anstelle einer Arbeit soll der übergebene oder abgefragte Name angezeigt werden.

Übung 3 Argumente Zur Lösung

Erweitern Sie die vorige Main-Methode um einen Rückgabewert. Dieser soll der Dateigröße entsprechen, sofern die Datei vorhanden ist; andernfalls soll er -1 lauten.

Lösungen

Lösung zu Übung 1 Definitionen Zur Übung

Die Aussagen 1, 2, 5 sind wahr, die Aussagen 3, 4, 6, 7 sind falsch.
Anmerkungen: Zu 6. Bei Prism ist ein einzelner String-Wert möglich. Zu 7. Es ist möglich, mit einem Integer als Rückgabewert zu arbeiten; aber das gilt nicht immer, sondern nur bei entsprechender Deklaration.

Lösung zu Übung 2 Argumente Zur Übung
Methode Main(String-Array args) ohne Rückgabewert
  String-Variable value deklarieren
  if (args fehlt)
  then
    Console.WriteLine(Fehlermeldung)
    value durch Console.ReadLine() bestimmen
  else
    value durch args[0] übernehmen
  endif
  Console.WriteLine(value)
  Console.ReadKey()
Ende der Methode

Lösung zu Übung 3 Argumente Zur Übung
Methode Main(String-Array args) mit Integer-Rückgabewert
  String-Variable value deklarieren
  Integer-Variable output deklarieren
  if (args fehlt)  /* unverändert */
  if (Datei existiert)
  then
    output wird die Dateigröße zugewiesen
  else
    output wird der Wert -1 zugewiesen
  endif
  Rückgabewert auf output setzen
Ende der Methode