Condividi tramite


Dichiarazioni di livello superiore: programmi senza metodi Main

Suggerimento

Novità dello sviluppo di software? Iniziare prima con le esercitazioni introduttive . Queste esercitazioni usano istruzioni di primo livello, quindi si ha già familiarità con le nozioni di base.

Cerchi l'alternativa al Main metodo? Per l'approccio esplicito al metodo, vedere Main.

Usare istruzioni di primo livello per le nuove app. Usando istruzioni di primo livello, è possibile scrivere codice eseguibile direttamente nella radice di un file.

Ecco un file Program.cs che è un programma C# completo:

Console.WriteLine("Hello World!");

Quando si crea una nuova app console usando dotnet new console, usa le istruzioni di primo livello per impostazione predefinita. Funzionano bene per i programmi di qualsiasi dimensione, dalle utilità di piccole dimensioni e funzioni di Azure alle applicazioni complete. Se si dispone di un'applicazione esistente che usa un metodo esplicito Main , non è necessario convertirla. Entrambi gli stili vengono compilati in codice equivalente.

Le sezioni seguenti illustrano le regole sulle operazioni che è possibile e non è possibile eseguire con le istruzioni di primo livello.

Regole del punto di ingresso

Un'applicazione deve avere un solo punto di ingresso. Un progetto può avere un solo file con istruzioni di primo livello, ma può avere un numero qualsiasi di file di codice sorgente che non dispongono di istruzioni di primo livello. È possibile scrivere in modo esplicito un Main metodo, ma non può funzionare come punto di ingresso. In un progetto con istruzioni di primo livello non è possibile usare l'opzione del -main compilatore per selezionare il punto di ingresso, anche se il progetto ha uno o più Main metodi.

Il compilatore genera un metodo da usare come punto di ingresso del programma per un progetto con istruzioni di primo livello. La firma del metodo dipende dal fatto che le istruzioni di primo livello contengano la parola chiave await o l'istruzione return. Nella tabella seguente viene illustrato l'aspetto della firma del metodo, usando il nome Main del metodo nella tabella per praticità.

Il codice di primo livello contiene Firma Main implicita
await e return static async Task<int> Main(string[] args)
await static async Task Main(string[] args)
return static int Main(string[] args)
No await o return static void Main(string[] args)

A partire da C# 14, i programmi possono essere app basate su file, in cui un singolo file contiene il programma. Esegui le app basate su file utilizzando il comando dotnet <file.cs>, o direttamente usando il nome del file su Unix, ad esempio ./file.cs. Quest'ultimo richiede l'inclusione della #!/usr/bin/env dotnet direttiva come prima riga e l'impostazione dell'autorizzazione di esecuzione (chmod +x <file>).

Direttive using

Per il singolo file contenente istruzioni di primo livello, le direttive using devono comparire prima in tale file, come nell'esempio seguente:

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;

Spazi dei nomi e definizioni dei tipi

Le istruzioni di primo livello sono implicitamente nello spazio dei nomi globale. Un file con istruzioni di primo livello può contenere anche spazi dei nomi e definizioni dei tipi, ma devono venire dopo le istruzioni di primo livello. Ad esempio:

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

Le istruzioni di primo livello possono fare riferimento alla args variabile per accedere a qualsiasi argomento della riga di comando passato all'app all'avvio. La args variabile non è mai null, ma è Length zero se non sono stati specificati argomenti della riga di comando. Ad esempio:

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

await e codice di uscita

Usare await per chiamare un metodo asincrono. Quando il codice di primo livello contiene await, il compilatore genera un punto di ingresso che restituisce un oggetto Task. Il runtime esegue il monitoraggio di Task per il completamento, mantenendo attivo il processo fino al termine di tutto il lavoro asincrono. Ad esempio:

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

Per restituire un codice di uscita al termine dell'applicazione, usare l'istruzione return . Il compilatore genera un punto di ingresso che restituisce Task<int> quando il codice contiene sia await e returno int quando contiene solo return. Ad esempio:

string? s = Console.ReadLine();

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