Main() und Befehlszeilenargumente

Die Main-Methode ist der Einstiegspunkt einer C#-Anwendung. Wenn die Anwendung gestartet wird, ist die Main-Methode die erste Methode, die aufgerufen wird.

In einem C#-Programm kann nur ein Einstiegspunkt vorhanden sein. Wenn Sie mehr als eine Klasse mit einer Main-Methode haben, müssen Sie das Programm mit der StartupObject-Compileroption kompilieren, um anzugeben, welche Main-Methode als Einstiegspunkt verwendet wird. Weitere Informationen finden Sie unter StartupObject (C#-Compileroptionen).

class TestClass
{
    static void Main(string[] args)
    {
        // Display the number of command line arguments.
        Console.WriteLine(args.Length);
    }
}

Sie können Top-Level-Anweisungen auch in einer Datei als Einstiegspunkt für Ihre Anwendung verwenden. Genau wie die Main-Methode können Top-Level-Anweisungen auch Werte zurückgeben und auf Befehlszeilenargumente zugreifen. Weitere Informationen finden Sie unter Top-Level-Anweisungen.

using System.Text;

StringBuilder builder = new();
builder.AppendLine("The following arguments are passed:");

// Display the command line arguments using the args variable.
foreach (var arg in args)
{
    builder.AppendLine($"Argument={arg}");
}

Console.WriteLine(builder.ToString());

// Return a success code.
return 0;

Übersicht

  • Die Main-Methode ist der Einstiegspunkt eines ausführbaren Programms. Hier beginnt und endet die Programmsteuerung.
  • Main muss innerhalb einer Klasse oder Struktur deklariert werden. Eine einschließende class kann static sein.
  • Main muss den Wert static haben.
  • Main kann einen beliebigen Zugriffsmodifizierer haben (mit Ausnahme von file).
  • Main kann den Rückgabetyp void, int, Task oder Task<int> aufweisen.
  • Wenn – und nur wenn – Main einen Task- oder Task<int>-Wert zurückgibt, darf die Deklaration von Main den async-Modifizierer enthalten. Dies schließt insbesondere eine async void Main-Methode aus.
  • Die Main-Methode kann mit oder ohne string[]-Parameter deklariert werden, der die Befehlszeilenargumente enthält. Bei Verwendung von Visual Studio zum Erstellen von Windows-Anwendungen können Sie den Parameter manuell hinzufügen oder die GetCommandLineArgs()-Methode verwenden, um die Befehlszeilenargumente abzurufen. Parameter werden als mit Null indizierte Befehlszeilenargumente gelesen. Im Gegensatz zu C und C++ wird der Name des Programms nicht als erstes Befehlszeilenargument im args-Array behandelt, es ist jedoch das erste Element der GetCommandLineArgs()-Methode.

Die folgende Liste zeigt die am häufigsten verwendeten Main-Deklarationen:

static void Main() { }
static int Main() { }
static void Main(string[] args) { }
static int Main(string[] args) { }
static async Task Main() { }
static async Task<int> Main() { }
static async Task Main(string[] args) { }
static async Task<int> Main(string[] args) { }

In den vorherigen Beispielen wurde kein Zugriffsmodifizierer angegeben, sodass standardmäßig implizit private verwendet wird. Dies ist gängige Praxis, es ist aber möglich, jeden expliziten Zugriffsmodifizierer anzugeben.

Tipp

Das Hinzufügen der async-Rückgabetypen Task und Task<int> vereinfacht den Programmcode, wenn Konsolenanwendungen asynchrone Vorgänge in Main starten und mit await darauf warten müssen.

Main()-Rückgabewerte

Sie können einen int-Wert aus der Main-Methode zurückgeben, indem Sie die Methode auf eine der folgenden Arten definieren:

Main-Deklaration Main-Methodencode
static int Main() Keine Verwendung von args oder await
static int Main(string[] args) Verwendet args, keine Verwendung von await
static async Task<int> Main() Keine Verwendung von args, verwendet await
static async Task<int> Main(string[] args) Verwendet args und await

Wenn der Rückgabewert von Main nicht verwendet wird, ermöglicht die Rückgabe von void oder Task etwas einfacheren Code.

Main-Deklaration Main-Methodencode
static void Main() Keine Verwendung von args oder await
static void Main(string[] args) Verwendet args, keine Verwendung von await
static async Task Main() Keine Verwendung von args, verwendet await
static async Task Main(string[] args) Verwendet args und await

Die Rückgabe von int oder Task<int> ermöglicht es dem Programm jedoch, Statusinformationen an andere Programme oder Skripts zu übermitteln, die die ausführbare Datei aufrufen.

Im folgenden Beispiel wird gezeigt, wie auf den Exitcode für den Prozess zugegriffen werden kann.

In diesem Beispiel werden Befehlszeilentools von .NET Core verwendet. Wenn Sie noch nicht mit den Befehlszeilentools von .NET Core vertraut sind, finden Sie weitere Informationen in diesem Artikel zu den ersten Schritten.

Erstellen Sie eine neue Anwendung, indem Sie dotnet new console ausführen. Ändern Sie die Main-Methode in program.cs folgendermaßen:

// Save this program as MainReturnValTest.cs.
class MainReturnValTest
{
    static int Main()
    {
        //...
        return 0;
    }
}

Wenn ein Programm in Windows ausgeführt wird, wird jeder Wert, der von der Funktion Main zurückgegeben wurde, in einer Umgebungsvariable gespeichert. Diese Umgebungsvariable kann abgerufen werden, indem ERRORLEVEL aus einer Batchdatei oder $LastExitCode aus PowerShell verwendet wird.

Sie können die Anwendung mithilfe des dotnet CLI-Befehls dotnet build erstellen.

Als Nächstes erstellen Sie ein PowerShell-Skript, das die Anwendung ausführt und die Ergebnisse anzeigt. Fügen Sie folgenden Code in eine Textdatei ein und speichern Sie diese als test.ps1 in dem Ordner, der das Projekt enthält. Führen Sie das PowerShell-Skript aus, indem Sie test.ps1 in die PowerShell-Eingabeaufforderung eingeben.

Da der Code null zurückgibt, wird die Batchdatei als erfolgreich gemeldet. Wenn Sie jedoch die Datei „MainReturnValTest.cs“ ändern, damit sie einen Wert ungleich null (0) zurückgibt, und das Programm anschließend neu kompilieren, wird eine nachfolgende Ausführung des PowerShell-Skripts einen Fehler melden.

dotnet run
if ($LastExitCode -eq 0) {
    Write-Host "Execution succeeded"
} else
{
    Write-Host "Execution Failed"
}
Write-Host "Return value = " $LastExitCode
Execution succeeded
Return value = 0

Asynchrone Hauptrückgabewerte

Wenn Sie einen async-Rückgabewert für Main deklarieren, generiert der Compiler den Codebaustein zum Aufrufen asynchroner Methoden in Main. Wenn Sie das async-Schlüsselwort nicht angeben, müssen Sie diesen Code selbst schreiben, wie im folgenden Beispiel gezeigt. Der Code im Beispiel stellt sicher, dass das Programm ausgeführt wird, bis der asynchrone Vorgang abgeschlossen ist:

class AsyncMainReturnValTest
{
    public static int Main()
    {
        return AsyncConsoleWork().GetAwaiter().GetResult();
    }

    private static async Task<int> AsyncConsoleWork()
    {
        // Main body here
        return 0;
    }
}

Dieser Codebaustein kann ersetzt werden durch:

class Program
{
    static async Task<int> Main(string[] args)
    {
        return await AsyncConsoleWork();
    }

    private static async Task<int> AsyncConsoleWork()
    {
        // main body here 
        return 0;
    }
}

Ein Vorteil der Deklarierung von Main als async ist, dass der Compiler immer den richtigen Code generiert.

Wenn der Einstiegspunkt der Anwendung Task oder Task<int> zurückgibt, generiert der Compiler einen neuen Eingangspunkt, der die Eingangspunktmethode abruft, die im Anwendungscode deklariert wurde. Unter der Annahme, dass dieser Einstiegspunkt als $GeneratedMain bezeichnet wird, generiert der Compiler den folgenden Code für diese Einstiegspunkte:

  • static Task Main() führt dazu, dass der Compiler das Äquivalent zu private static void $GeneratedMain() => Main().GetAwaiter().GetResult(); ausgibt
  • static Task Main(string[]) führt dazu, dass der Compiler das Äquivalent zu private static void $GeneratedMain(string[] args) => Main(args).GetAwaiter().GetResult(); ausgibt
  • static Task<int> Main() führt dazu, dass der Compiler das Äquivalent zu private static int $GeneratedMain() => Main().GetAwaiter().GetResult(); ausgibt
  • static Task<int> Main(string[]) führt dazu, dass der Compiler das Äquivalent zu private static int $GeneratedMain(string[] args) => Main(args).GetAwaiter().GetResult(); ausgibt

Hinweis

Wäre im Beispiel der Modifizierer async auf die Methode Main angewendet worden, hätte der Compiler denselben Code generiert.

Befehlszeilenargumente

Sie können Argumente an die Main- Methode senden, indem Sie die Methode auf eine der folgenden Arten definieren:

Main-Deklaration Main-Methodencode
static void Main(string[] args) Kein Rückgabewert, keine Verwendung von await
static int Main(string[] args) Rückgabewert, keine Verwendung von await
static async Task Main(string[] args) Kein Rückgabewert, verwendet await
static async Task<int> Main(string[] args) Rückgabewert, verwendet await

Wenn die Argumente nicht verwendet werden, können Sie args in der Methodendeklaration auslassen, um etwas einfacheren Code zu erhalten:

Main-Deklaration Main-Methodencode
static void Main() Kein Rückgabewert, keine Verwendung von await
static int Main() Rückgabewert, keine Verwendung von await
static async Task Main() Kein Rückgabewert, verwendet await
static async Task<int> Main() Rückgabewert, verwendet await

Hinweis

Sie können auch Environment.CommandLine oder Environment.GetCommandLineArgs verwenden, um an einem beliebigen Punkt in einer Konsolen- oder Windows Forms-Anwendung auf die Befehlszeilenargumente zuzugreifen. Sie müssen die Deklaration von Main manuell ändern, um in der Main-Methodendeklaration in einer Windows Forms-Anwendung Befehlszeilenargumente zu aktivieren. In dem vom Windows Forms-Designer generierten Code wird Main ohne Eingabeparameter erstellt.

Der Parameter der Main-Methode ist ein String-Array, das die Befehlszeilenargumente darstellt. Normalerweise bestimmen Sie, ob Argumente vorhanden sind, indem Sie z. B. die Length-Eigenschaft testen:

if (args.Length == 0)
{
    System.Console.WriteLine("Please enter a numeric argument.");
    return 1;
}

Tipp

Das args-Array darf nicht NULL sein. Daher ist es sicher, ohne Überprüfung auf NULL auf die Length-Eigenschaft zuzugreifen.

Sie können die Zeichenfolgenargumente auch mit der Convert-Klasse oder der Parse-Methode in numerische Typen konvertieren. Die folgende Anweisung konvertiert z. B. string mithilfe der long-Methode in eine Parse-Zahl:

long num = Int64.Parse(args[0]);

Sie können auch den C#-Typ long verwenden, der als Alias für Int64 fungiert:

long num = long.Parse(args[0]);

Sie können für dieselbe Aufgabe auch die Convert-Klassenmethode ToInt64 verwenden:

long num = Convert.ToInt64(s);

Weitere Informationen finden Sie unter Parse und Convert.

Tipp

Das Analysieren von Befehlszeilenargumenten kann komplex sein. Ziehen Sie die Verwendung der Bibliothek System.CommandLine (derzeit in der Betaphase) in Erwägung, um den Prozess zu vereinfachen.

Im folgenden Beispiel wird gezeigt, wie Befehlszeilenargumente in einer Konsolenanwendung verwendet werden. Die Anwendung übernimmt zur Laufzeit ein Argument, konvertiert das Argument in eine ganze Zahl und berechnet die Fakultät der Zahl. Wenn keine Argumente übergeben werden, erzeugt die Anwendung eine Meldung, in der die richtige Verwendung des Programms erläutert wird.

Führen Sie die folgenden Schritte aus, um die Anwendung von einer Eingabeaufforderung aus zu kompilieren und auszuführen:

  1. Fügen Sie den folgenden Code in einem beliebigen Text-Editor ein, und speichern Sie die Datei als Textdatei mit dem Namen Factorial.cs.

    public class Functions
    {
        public static long Factorial(int n)
        {
            // Test for invalid input.
            if ((n < 0) || (n > 20))
            {
                return -1;
            }
    
            // Calculate the factorial iteratively rather than recursively.
            long tempResult = 1;
            for (int i = 1; i <= n; i++)
            {
                tempResult *= i;
            }
            return tempResult;
        }
    }
    
    class MainClass
    {
        static int Main(string[] args)
        {
            // Test if input arguments were supplied.
            if (args.Length == 0)
            {
                Console.WriteLine("Please enter a numeric argument.");
                Console.WriteLine("Usage: Factorial <num>");
                return 1;
            }
    
            // Try to convert the input arguments to numbers. This will throw
            // an exception if the argument is not a number.
            // num = int.Parse(args[0]);
            int num;
            bool test = int.TryParse(args[0], out num);
            if (!test)
            {
                Console.WriteLine("Please enter a numeric argument.");
                Console.WriteLine("Usage: Factorial <num>");
                return 1;
            }
    
            // Calculate factorial.
            long result = Functions.Factorial(num);
    
            // Print result.
            if (result == -1)
                Console.WriteLine("Input must be >= 0 and <= 20.");
            else
                Console.WriteLine($"The Factorial of {num} is {result}.");
    
            return 0;
        }
    }
    // If 3 is entered on command line, the
    // output reads: The factorial of 3 is 6.
    
  2. Öffnen Sie über den Bildschirm Starten oder das Menü Starten eine Visual Studio Developer-Eingabeaufforderung, und navigieren Sie dann zu dem Ordner, der die Datei enthält, die Sie erstellt haben.

  3. Geben Sie den folgenden Befehl ein, um die Anwendung zu kompilieren.

    dotnet build

    Wenn die Anwendung keine Kompilierungsfehler aufweist, wird eine ausführbare Datei mit dem Namen Factorial.exe erstellt.

  4. Geben Sie den folgenden Befehl ein, um die Fakultät von 3 zu berechnen:

    dotnet run -- 3

  5. Durch den Befehl wird die folgende Ausgabe generiert: The factorial of 3 is 6.

Hinweis

Wenn Sie eine Anwendung in Visual Studio ausführen, können Sie Befehlszeilenargumente auf der Seite „Debuggen“, Projekt-Designer angeben.

C#-Sprachspezifikation

Weitere Informationen erhalten Sie unter C#-Sprachspezifikation. Die Sprachspezifikation ist die verbindliche Quelle für die Syntax und Verwendung von C#.

Siehe auch