Main() e argomenti della riga di comando
Il metodo Main
è il punto di ingresso di un'applicazione C#. All'avvio dell'applicazione, Main
è il primo metodo richiamato.
In un programma C# può essere presente un solo punto di ingresso. Se si dispone di più classi con un metodo Main
, è necessario compilare il programma con l'opzione del compilatore StartupObject per specificare quale metodo Main
usare come punto di ingresso. Per altre informazioni, vedere StartupObject (opzioni del compilatore C#).
class TestClass
{
static void Main(string[] args)
{
// Display the number of command line arguments.
Console.WriteLine(args.Length);
}
}
È anche possibile usare istruzioni di primo livello in un file come punto di ingresso per l'applicazione.
Analogamente al metodo Main
, anche le istruzioni di primo livello possono restituire valori e accedere agli argomenti della riga di comando.
Per altre informazioni, vedere Istruzioni di primo livello.
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;
Panoramica
- Il metodo
Main
è il punto di ingresso di un programma eseguibile, ovvero il punto in cui il controllo del programma inizia e termina. Main
deve essere dichiarato in una classe o uno struct. L'elementoclass
contenitore può esserestatic
.- Il parametro
Main
deve essere impostato sustatic
. Main
può includere qualsiasi modificatore di accesso (eccettofile
).Main
può avere un tipo restituitovoid
,int
,Task
oTask<int>
.- Se e solo se
Main
restituisceTask
oTask<int>
, la dichiarazione diMain
può includere il modificatoreasync
. Ciò esclude in modo specifico un metodoasync void Main
. - Il metodo
Main
può essere dichiarato con o senza un parametrostring[]
contenente argomenti della riga di comando. Quando si usa Visual Studio per creare applicazioni Windows, è possibile aggiungere il parametro manualmente oppure usare il metodo GetCommandLineArgs() per ottenere gli argomenti della riga di comando. I parametri vengono letti come argomenti della riga di comando a indice zero. A differenza di C e C++, il nome del programma non viene considerato come il primo argomento della riga di comando nella matriceargs
, ma è il primo elemento del metodo GetCommandLineArgs().
L'elenco seguente mostra le dichiarazioni di Main
più comuni:
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) { }
Gli esempi precedenti non specificano un modificatore di accesso, quindi sono private
in modo implicito per impostazione predefinita. Si tratta di un comportamento standard, ma è possibile specificare qualsiasi modificatore di accesso esplicito.
Suggerimento
L'aggiunta dei tipi restituiti async
, Task
e Task<int>
semplifica il codice del programma quando è necessario avviare le applicazioni console e per operazioni asincrone await
in Main
.
Valori restituiti da Main()
È possibile restituire un int
dal metodo Main
definendo il metodo in uno dei modi seguenti:
Dichiarazione di Main |
codice del metodoMain |
---|---|
static int Main() |
Nessun uso di args o await |
static int Main(string[] args) |
Usa args , senza uso di await |
static async Task<int> Main() |
Nessun uso di args , usa await |
static async Task<int> Main(string[] args) |
Usa args e await |
Se il valore restituito da Main
non viene usato, la restituzione di void
o Task
consente codice leggermente più semplice.
Dichiarazione di Main |
codice del metodoMain |
---|---|
static void Main() |
Nessun uso di args o await |
static void Main(string[] args) |
Usa args , senza uso di await |
static async Task Main() |
Nessun uso di args , usa await |
static async Task Main(string[] args) |
Usa args e await |
Tuttavia, la restituzione di int
o Task<int>
consente al programma di comunicare informazioni sullo stato ad altri programmi o script che richiamano il file eseguibile.
Nell'esempio seguente viene illustrato come è possibile accedere al codice di uscita per il processo.
Questo esempio usa strumenti da riga di comando di .NET Core. Se non si ha familiarità con gli strumenti da riga di comando di .NET Core, è possibile ottenere informazioni su di essi in questo articolo introduttivo.
Creare una nuova applicazione eseguendo dotnet new console
. Convertire il metodo Main
in program.cs come indicato di seguito:
// Save this program as MainReturnValTest.cs.
class MainReturnValTest
{
static int Main()
{
//...
return 0;
}
}
Quando si esegue un programma in ambiente Windows, qualsiasi valore restituito dalla funzione Main
viene archiviato in una variabile di ambiente. Questa variabile di ambiente può essere recuperata mediante ERRORLEVEL
da un file batch o mediante $LastExitCode
da PowerShell.
È possibile compilare l'applicazione usando il comando dotnet build
dell'interfaccia della riga di comando di dotnet.
Quindi creare uno script di PowerShell per eseguire l'applicazione e visualizzare il risultato. Incollare il codice seguente in un file di testo e salvarlo come test.ps1
nella cartella che contiene il progetto. Eseguire lo script di PowerShell digitando test.ps1
al prompt di PowerShell.
Poiché il codice restituisce zero, il file batch indicherà un esito positivo. Tuttavia, se si modifica MainReturnValTest.cs per restituire un valore diverso da zero e poi ricompilare il programma, l'esecuzione successiva dello script di PowerShell segnala un errore.
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
Valori restituiti da Async Main
Quando si dichiara un valore restituito async
per Main
, il compilatore genera il codice boilerplate per chiamare metodi asincroni in Main
. Se non si specifica la parola chiave async
, è necessario scrivere manualmente il codice, come illustrato nell'esempio seguente. Il codice nell'esempio garantisce che il programma venga eseguito fino al completamento dell'operazione asincrona:
class AsyncMainReturnValTest
{
public static int Main()
{
return AsyncConsoleWork().GetAwaiter().GetResult();
}
private static async Task<int> AsyncConsoleWork()
{
// Main body here
return 0;
}
}
Questo codice boilerplate può essere sostituito da:
class Program
{
static async Task<int> Main(string[] args)
{
return await AsyncConsoleWork();
}
private static async Task<int> AsyncConsoleWork()
{
// main body here
return 0;
}
}
Un vantaggio della dichiarazione di Main
come async
è che il compilatore genera sempre il codice corretto.
Quando il punto di ingresso dell'applicazione restituisce Task
o Task<int>
il compilatore genera un nuovo punto di ingresso che chiama il metodo del punto di ingresso dichiarato nel codice dell'applicazione. Supponendo che questo punto di ingresso sia denominato $GeneratedMain
, il compilatore genera il codice seguente per questi punti di ingresso:
static Task Main()
: il compilatore produce l'equivalente diprivate static void $GeneratedMain() => Main().GetAwaiter().GetResult();
static Task Main(string[])
: il compilatore produce l'equivalente diprivate static void $GeneratedMain(string[] args) => Main(args).GetAwaiter().GetResult();
static Task<int> Main()
: il compilatore produce l'equivalente diprivate static int $GeneratedMain() => Main().GetAwaiter().GetResult();
static Task<int> Main(string[])
: il compilatore produce l'equivalente diprivate static int $GeneratedMain(string[] args) => Main(args).GetAwaiter().GetResult();
Nota
Se negli esempi si fosse usato il modificatore async
sul metodo Main
il compilatore avrebbe generato lo stesso codice.
Argomenti della riga di comando
È possibile inviare argomenti al metodo Main
definendo il metodo in uno dei modi seguenti:
Dichiarazione di Main |
codice del metodoMain |
---|---|
static void Main(string[] args) |
Nessun valore restituito, nessun uso di await |
static int Main(string[] args) |
Valore restituito, nessun uso di await |
static async Task Main(string[] args) |
Nessun valore restituito, usa await |
static async Task<int> Main(string[] args) |
Valore restituito, usa await |
Se non si usano gli argomenti, è possibile omettere args
dalla dichiarazione del metodo per semplificare leggermente il codice:
Dichiarazione di Main |
codice del metodoMain |
---|---|
static void Main() |
Nessun valore restituito, nessun uso di await |
static int Main() |
Valore restituito, nessun uso di await |
static async Task Main() |
Nessun valore restituito, usa await |
static async Task<int> Main() |
Valore restituito, usa await |
Nota
È anche possibile usare Environment.CommandLine o Environment.GetCommandLineArgs per accedere agli argomenti della riga di comando da qualsiasi punto in una console o Windows Forms Application. Per abilitare gli argomenti della riga di comando nella dichiarazione del metodo Main
in una Windows Forms Application, è necessario modificare manualmente la dichiarazione di Main
. Il codice generato dalla finestra di progettazione di Windows Form crea Main
senza un parametro di input.
Il parametro del metodo Main
è una matrice String che rappresenta gli argomenti della riga di comando. In genere si determina se gli argomenti esistono eseguendo il test della proprietà Length
, ad esempio:
if (args.Length == 0)
{
System.Console.WriteLine("Please enter a numeric argument.");
return 1;
}
Suggerimento
La matrice args
non può essere Null. Quindi, è sicuro accedere alla proprietà Length
senza il controllo Null.
È anche possibile convertire gli argomenti stringa in tipi numerici con la classe Convert o il metodo Parse
. Ad esempio, l'istruzione seguente converte string
in un numero long
con il metodo Parse:
long num = Int64.Parse(args[0]);
È anche possibile usare il tipo C# long
, che fa da alias per Int64
:
long num = long.Parse(args[0]);
Nella classe Convert
il metodo ToInt64
consente di eseguire la stessa operazione:
long num = Convert.ToInt64(s);
Per altre informazioni, vedere Parse e Convert.
Suggerimento
L'analisi degli argomenti della riga di comando può essere complessa. Per semplificare il processo, provare a usare la libreria System.CommandLine, attualmente disponibile in versione beta.
L'esempio seguente illustra come usare gli argomenti della riga di comando in un'applicazione console. L'applicazione accetta un argomento in fase di esecuzione, lo converte in un numero intero e calcola il fattoriale del numero. Se non viene specificato nessun argomento, l'applicazione produce un messaggio che descrive l'uso corretto del programma.
Per compilare ed eseguire l'applicazione al prompt dei comandi, seguire questa procedura:
Incollare il codice seguente in qualsiasi editor di testo e quindi salvare il file come file di testo con il nome 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.
Nella schermata Start o menu Start, aprire una finestra del prompt dei comandi per gli sviluppatori di Visual Studio e quindi passare alla cartella contenente il file creato.
Immettere il seguente comando per compilare l'applicazione.
dotnet build
Se l'applicazione non presenta errori di compilazione, viene creato un file eseguibile denominato Factorial.exe.
Immettere il comando seguente per calcolare il fattoriale di 3:
dotnet run -- 3
Il comando produce il seguente output:
The factorial of 3 is 6.
Nota
Quando si esegue un'applicazione in Visual Studio, è possibile specificare argomenti della riga di comando nella Pagina Debug, Progettazione progetti.
Specifiche del linguaggio C#
Per altre informazioni, vedere la specifica del linguaggio C#. La specifica del linguaggio costituisce il riferimento ufficiale principale per la sintassi e l'uso di C#.