Freigeben über


Anweisungen auf oberster Ebene: Programme ohne Main-Methoden

Tipp

Neu bei der Entwicklung von Software? Beginnen Sie zuerst mit den Lernprogrammen " Erste Schritte ". Diese Lernprogramme verwenden Anweisungen auf oberster Ebene, damit Sie bereits mit den Grundlagen vertraut sind.

Suchen Sie nach einer Alternative zur Main Methode? Informationen zum expliziten Methodenansatz finden Sie unter "Main".

Verwenden Sie Anweisungen auf oberster Ebene für neue Apps. Mithilfe von Anweisungen auf oberster Ebene können Sie ausführbaren Code direkt im Stammverzeichnis einer Datei schreiben.

Hier ist eine Program.cs Datei, die ein vollständiges C#-Programm ist:

Console.WriteLine("Hello World!");

Wenn Sie eine neue Konsolen-App mithilfe von dotnet new console erstellen, werden standardmäßig Anweisungen der obersten Ebene genutzt. Sie funktionieren gut für Programme jeder Größe – von kleinen Dienstprogrammen und Azure Functions bis hin zu vollständigen Anwendungen. Wenn Sie über eine vorhandene Anwendung verfügen, die eine explizite Main Methode verwendet, müssen Sie sie nicht konvertieren. Beide Stile werden in gleichwertigen Code kompiliert.

In den folgenden Abschnitten werden die Regeln für zulässige und unzulässige Anweisungen auf oberster Ebene erläutert.

Einstiegspunktregeln

Eine Anwendung muss nur einen Einstiegspunkt haben. Ein Projekt kann nur eine Datei mit Anweisungen auf oberster Ebene haben, aber es kann eine beliebige Anzahl von Quellcodedateien haben, die keine Anweisungen auf oberster Ebene haben. Sie können eine Main Methode explizit schreiben, aber sie kann nicht als Einstiegspunkt funktionieren. In einem Projekt mit Anweisungen auf oberster Ebene können Sie die -main Compileroption nicht verwenden, um den Einstiegspunkt auszuwählen, auch wenn das Projekt über eine oder Main mehrere Methoden verfügt.

Der Compiler generiert eine Methode, die als Programmeinstiegspunkt für ein Projekt mit Anweisungen auf oberster Ebene fungiert. Die Signatur der Methode hängt davon ab, ob die Anweisungen auf oberster Ebene das await-Schlüsselwort oder die return-Anweisung enthalten. In der folgenden Tabelle wird gezeigt, wie die Methodensignatur aussieht, wobei der Methodenname Main in der Tabelle zur Vereinfachung verwendet wird.

Code auf oberster Ebene enthält Folgendes: Implizite Main-Signatur
await und return static async Task<int> Main(string[] args)
await static async Task Main(string[] args)
return static int Main(string[] args)
Kein await oder return static void Main(string[] args)

Ab C# 14 können Programme dateibasierte Apps sein, bei denen eine einzelne Datei das Programm enthält. Sie führen dateibasierte Apps mithilfe des Befehls dotnet <file.cs>oder mithilfe der #!/usr/bin/env dotnet Direktive als erste Zeile aus (nur Unix-Shells).

using-Anweisungen

Für die einzelne Datei, die Anweisungen auf oberster Ebene enthält, müssen using Direktiven zuerst in dieser Datei stehen, wie das folgende Beispiel zeigt.

using System.Text;

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

foreach (var arg in args)
{
    builder.AppendLine($"Argument={arg}");
}

Console.WriteLine(builder.ToString());

return 0;

Namespaces und Typdefinitionen

Anweisungen auf oberster Ebene sind implizit im globalen Namespace enthalten. Eine Datei mit Anweisungen auf oberster Ebene kann auch Namespaces und Typdefinitionen enthalten, sie müssen aber nach den Anweisungen auf oberster Ebene platziert werden. Zum Beispiel:

MyClass.TestMethod();
MyNamespace.MyClass.MyMethod();

public class MyClass
{
    public static void TestMethod()
    {
        Console.WriteLine("Hello World!");
    }
}

namespace MyNamespace
{
    class MyClass
    {
        public static void MyMethod()
        {
            Console.WriteLine("Hello World from MyNamespace.MyClass.MyMethod!");
        }
    }
}

args

Anweisungen der obersten Ebene können auf die args Variable verweisen, um auf alle Befehlszeilenargumente zuzugreifen, die beim Start an die App übergeben werden. Die args Variable ist niemals null, hat aber den Wert Length null, wenn keine Befehlszeilenargumente angegeben wurden. Zum Beispiel:

if (args.Length > 0)
{
    foreach (var arg in args)
    {
        Console.WriteLine($"Argument={arg}");
    }
}
else
{
    Console.WriteLine("No arguments");
}

await und Exit-Code

Verwenden Sie await, um eine asynchrone Methode aufzurufen. Wenn Ihr Code auf oberster Ebene await enthält, generiert der Compiler einen Einstiegspunkt, der ein Task zurückgibt. Die Laufzeit überwacht Task für den Abschluss und hält den Prozess aktiv, bis alle asynchronen Aufgaben abgeschlossen sind. Zum Beispiel:

Console.Write("Hello ");
await Task.Delay(5000);
Console.WriteLine("World!");

Verwenden Sie die return Anweisung, um einen Ausgangscode zurückzugeben, wenn die Anwendung endet. Der Compiler generiert einen Einstiegspunkt, der Task<int> zurückgibt, wenn Ihr Code sowohl await als auch return enthält, oder int, wenn er nur return enthält. Zum Beispiel:

string? s = Console.ReadLine();

int returnValue = int.Parse(s ?? "-1");
return returnValue;