Anweisungen auf oberster Ebene: Programme ohne Main-Methoden

Sie müssen eine Main-Methode nicht mehr explizit in ein Konsolenanwendungsprojekt einschließen. Stattdessen können Sie die Funktion Anweisungen auf oberster Ebene verwenden, um den Code zu minimieren, den Sie schreiben müssen.

Mithilfe von Anweisungen der obersten Ebene können Sie ausführbaren Code direkt im Stamm einer Datei schreiben, sodass der Code nicht in einer Klasse oder Methode umschlossen werden muss. Dies bedeutet, dass Sie Programme ohne eine Program-Klasse und eine Main-Methode erstellen können. In diesem Fall generiert der Compiler eine Program-Klasse mit einer Enstiegspunktmethode für die Anwendung. Der Name der generierten Methode ist nicht Main, sondern ein Implementierungsdetail, auf das Ihr Code nicht direkt verweisen kann.

Im Folgenden sehen Sie die Datei Program.cs, die in C# 10 ein vollständiges C#-Programm ist:

Console.WriteLine("Hello World!");

Mit Anweisungen auf oberster Ebene können Sie einfache Programme für kleine Dienstprogramme wie Azure Functions und GitHub Actions schreiben. Sie erleichtern auch neuen C#-Programmierern den Einstieg in das Erlernen und Schreiben von Code.

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

Nur eine Datei auf oberster Ebene

Eine Anwendung muss nur einen Einstiegspunkt haben. Ein Projekt kann nur eine Datei mit Anweisungen auf oberster Ebene enthalten. Das Einfügen von Anweisungen auf oberster Ebene in mehrere Dateien in einem Projekt führt zu folgendem Compilerfehler:

CS8802 Only one compilation unit can have top-level statements (Nur eine Kompilierungseinheit kann Anweisungen auf oberster Ebene aufweisen).

Ein Projekt kann beliebig viele zusätzliche Quellcodedateien aufweisen, die keine Anweisungen auf oberster Ebene aufweisen.

Keine weiteren Einstiegspunkte

Sie können eine Main-Methode explizit schreiben, aber sie kann nicht als Einstiegspunkt fungieren. Der Compiler gibt folgende Warnung aus:

CS7022 The entry point of the program is global code; ignoring 'Main()' entry point (Der Einstiegspunkt des Programms ist globaler Code. Der Einstiegspunkt 'Main()' wird ignoriert).

In einem Projekt mit Anweisungen auf oberster Ebene können Sie die Compileroption -main nicht verwenden, um den Einstiegspunkt auszuwählen, auch wenn das Projekt mindestens eine Main-Methode aufweist.

using-Direktiven

Wenn Sie using-Direktiven einschließen, müssen diese zuerst in der Datei vorkommen, wie im folgenden Beispiel gezeigt:

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;

Globaler Namespace

Anweisungen auf oberster Ebene sind implizit im globalen Namespace enthalten.

Namespaces und Typdefinitionen

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. 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 auf oberster Ebene können auf die args-Variable verweisen, um auf eingegebene Befehlszeilenargumente zuzugreifen. Die args-Variable ist nie NULL, aber Ihr Length ist null, wenn keine Befehlszeilenargumente angegeben wurden. Beispiel:

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

await

Sie können eine asynchrone Methode aufrufen, indem Sie await verwenden. Beispiel:

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

Exitcode für den Prozess

Um beim Beenden der Anwendung einen int-Wert zurückzugeben, verwenden Sie die return-Anweisung wie in einer Main-Methode, die einen int-Wert zurückgibt. Beispiel:

string? s = Console.ReadLine();

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

Implizite Einstiegspunktmethode

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. Die folgende Tabelle zeigt, wie die Methodensignatur aussehen würde, wobei der Einfachheit halber der Methodenname Main in der Tabelle 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)

C#-Sprachspezifikation

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

Featurespezifikation: Anweisungen auf oberster Ebene