Main() y argumentos de línea de comandos
El método Main
es el punto de entrada de una aplicación de C# Cuando se inicia la aplicación, el método Main
es el primero que se invoca.
Solo puede haber un punto de entrada en un programa de C#. Si hay más de una clase que tenga un método Main
, deberá compilar el programa con la opción del compilador StartupObject para especificar qué método Main
quiere utilizar como punto de entrada. Para obtener más información, consulte StartupObject (opciones del compilador de C#).
class TestClass
{
static void Main(string[] args)
{
// Display the number of command line arguments.
Console.WriteLine(args.Length);
}
}
También puede usar instrucciones de nivel superior en un archivo como punto de entrada para la aplicación.
Al igual que el método Main
, las instrucciones de nivel superior también pueden devolver valores y acceder a los argumentos de la línea de comandos.
Para más información, consulte Instrucciones de nivel superior.
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;
Información general
- El método
Main
es el punto de entrada de un programa ejecutable; es donde se inicia y finaliza el control del programa. Main
debe declararse dentro de una clase o estructura. Laclass
envolvente puede serstatic
.Main
debe serstatic
.Main
puede tener cualquier modificador de acceso (exceptofile
).Main
puede tener un tipo de valor devueltovoid
,int
,Task
oTask<int>
.- Solo si
Main
devuelve un tipo de valor devueltoTask
oTask<int>
, la declaración deMain
puede incluir el modificadorasync
, Esto excluye específicamente un métodoasync void Main
. - El método
Main
se puede declarar con o sin un parámetrostring[]
que contiene los argumentos de línea de comandos. Al usar Visual Studio para crear aplicaciones Windows, se puede agregar el parámetro manualmente o usar el método GetCommandLineArgs() con el fin de obtener los argumentos de la línea de comandos. Los parámetros se leen como argumentos de línea de comandos indizados con cero. A diferencia de C y C++, el nombre del programa no se trata como el primer argumento de línea de comandos en la matrizargs
, pero es el primer elemento del método GetCommandLineArgs().
En la lista siguiente, se muestran las declaraciones Main
más comunes:
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) { }
Los ejemplos anteriores no especifican un modificador de acceso, por lo que son implícitamente private
de forma predeterminada. Esto es típico, pero es posible especificar cualquier modificador de acceso explícito.
Sugerencia
Al agregar los tipos de valor devuelto async
, Task
y Task<int>
, se simplifica el código de programa cuando las aplicaciones de consola tienen que realizar tareas de inicio y await
de operaciones asincrónicas en Main
.
Valores devueltos Main()
Puede devolver un objeto int
desde el método Main
si lo define de una de las siguientes maneras:
declaración Main |
Código del método Main |
---|---|
static int Main() |
No se usa args ni await |
static int Main(string[] args) |
Se usa args , no se usa await |
static async Task<int> Main() |
No se usa args , se usa await |
static async Task<int> Main(string[] args) |
Se usan args y await |
Si el valor devuelto de Main
no se usa, la devolución de void
o Task
permite que el código sea ligeramente más sencillo.
declaración Main |
Código del método Main |
---|---|
static void Main() |
No se usa args ni await |
static void Main(string[] args) |
Se usa args , no se usa await |
static async Task Main() |
No se usa args , se usa await |
static async Task Main(string[] args) |
Se usan args y await |
Pero, si se devuelve int
o Task<int>
, el programa puede comunicar información de estado a otros programas o scripts que invocan el archivo ejecutable.
En el ejemplo siguiente se muestra cómo se puede acceder al código de salida para el proceso.
En este ejemplo se usan las herramientas de línea de comandos de .NET Core. Si no está familiarizado con las herramientas de línea de comandos de .NET Core, puede obtener información sobre ellas en este artículo de introducción.
Cree una aplicación mediante la ejecución de dotnet new console
. Modifique el método Main
en Program.cs como se indica a continuación:
// Save this program as MainReturnValTest.cs.
class MainReturnValTest
{
static int Main()
{
//...
return 0;
}
}
Cuando un programa se ejecuta en Windows, cualquier valor devuelto por la función Main
se almacena en una variable de entorno. Esta variable de entorno se puede recuperar mediante ERRORLEVEL
desde un archivo por lotes, o mediante $LastExitCode
desde PowerShell.
Puede compilar la aplicación mediante el comando dotnet build
de la CLI de dotnet.
Después, cree un script de PowerShell para ejecutar la aplicación y mostrar el resultado. Pegue el código siguiente en un archivo de texto y guárdelo como test.ps1
en la carpeta que contiene el proyecto. Ejecute el script de PowerShell. Para ello, escriba test.ps1
en el símbolo del sistema de PowerShell.
Dado que el código devuelve el valor cero, el archivo por lotes comunicará un resultado satisfactorio. En cambio, si cambia MainReturnValTest.cs para que devuelva un valor distinto de cero y luego vuelve a compilar el programa, la ejecución posterior del script de PowerShell informará de que se ha producido un error.
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
Valores devueltos asincrónicos de Main
Cuando se declara un valor devuelto async
para Main
, el compilador genera el código reutilizable para llamar a métodos asincrónicos en Main
. Si no especifica la palabra clave async
, debe escribir ese código usted mismo, como se muestra en el siguiente ejemplo. El código del ejemplo garantiza que el programa se ejecute hasta que se complete la operación asincrónica:
class AsyncMainReturnValTest
{
public static int Main()
{
return AsyncConsoleWork().GetAwaiter().GetResult();
}
private static async Task<int> AsyncConsoleWork()
{
// Main body here
return 0;
}
}
Este código reutilizable se puede reemplazar por:
class Program
{
static async Task<int> Main(string[] args)
{
return await AsyncConsoleWork();
}
private static async Task<int> AsyncConsoleWork()
{
// main body here
return 0;
}
}
Una ventaja de declarar Main
como async
es que el compilador siempre genera el código correcto.
Cuando el punto de entrada de la aplicación devuelve Task
o Task<int>
, el compilador genera un nuevo punto de entrada que llama al método de punto de entrada declarado en el código de la aplicación. Suponiendo que este punto de entrada se denomina $GeneratedMain
, el compilador genera el código siguiente para estos puntos de entrada:
static Task Main()
hace que el compilador emita el equivalente deprivate static void $GeneratedMain() => Main().GetAwaiter().GetResult();
static Task Main(string[])
hace que el compilador emita el equivalente deprivate static void $GeneratedMain(string[] args) => Main(args).GetAwaiter().GetResult();
static Task<int> Main()
hace que el compilador emita el equivalente deprivate static int $GeneratedMain() => Main().GetAwaiter().GetResult();
static Task<int> Main(string[])
hace que el compilador emita el equivalente deprivate static int $GeneratedMain(string[] args) => Main(args).GetAwaiter().GetResult();
Nota
Si en los ejemplos se usase el modificador async
en el método Main
, el compilador generaría el mismo código.
Argumentos de la línea de comandos
Puede enviar argumentos al método Main
definiéndolo de una de las siguientes maneras:
declaración Main |
Código del método Main |
---|---|
static void Main(string[] args) |
No hay valores devueltos, no se usa await |
static int Main(string[] args) |
Valor devuelto, no se usa await |
static async Task Main(string[] args) |
No hay valores devueltos, se usa await |
static async Task<int> Main(string[] args) |
Valor devuelto, se usa await |
Si no se usan los argumentos, puede omitir args
de la declaración del método para simplificar ligeramente el código:
declaración Main |
Código del método Main |
---|---|
static void Main() |
No hay valores devueltos, no se usa await |
static int Main() |
Valor devuelto, no se usa await |
static async Task Main() |
No hay valores devueltos, se usa await |
static async Task<int> Main() |
Valor devuelto, se usa await |
Nota
También puede usar Environment.CommandLine o Environment.GetCommandLineArgs para acceder a los argumentos de la línea de comandos desde cualquier punto de una consola o de una aplicación de Windows Forms. Para habilitar los argumentos de la línea de comandos en la declaración del método Main
de una aplicación Windows Forms, tendrá que modificar manualmente la declaración de Main
. El código generado por el diseñador de Windows Forms crea un Main
sin ningún parámetro de entrada.
El parámetro del método Main
es una matriz String que representa los argumentos de la línea de comandos. Normalmente, para determinar si hay argumentos, se prueba la propiedad Length
; por ejemplo:
if (args.Length == 0)
{
System.Console.WriteLine("Please enter a numeric argument.");
return 1;
}
Sugerencia
La matriz args
no puede ser NULL. así que es seguro acceder a la propiedad Length
sin comprobar los valores NULL.
También puede convertir los argumentos de cadena en tipos numéricos mediante la clase Convert o el método Parse
. Por ejemplo, la siguiente instrucción convierte la string
en un número long
mediante el método Parse:
long num = Int64.Parse(args[0]);
También se puede usar el tipo de C# long
, que tiene como alias Int64
:
long num = long.Parse(args[0]);
También puede usar el método ToInt64
de la clase Convert
para hacer lo mismo:
long num = Convert.ToInt64(s);
Para obtener más información, vea Parse y Convert.
Sugerencia
El análisis de argumentos de línea de comandos puede ser complejo. Considere la posibilidad de usar la biblioteca System.CommandLine (actualmente en versión beta) para simplificar el proceso.
En el ejemplo siguiente se muestra cómo usar argumentos de la línea de comandos en una aplicación de consola. La aplicación toma un argumento en tiempo de ejecución, lo convierte en un entero y calcula el factorial del número. Si no se proporciona ningún argumento, la aplicación emite un mensaje en el que se explica el uso correcto del programa.
Para compilar y ejecutar la aplicación desde un símbolo del sistema, siga estos pasos:
Pegue el código siguiente en cualquier editor de texto, y después guarde el archivo como archivo de texto con el nombre 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.
En la pantalla Inicio o en el menú Inicio, abra una ventana del Símbolo del sistema para desarrolladores de Visual Studio y navegue hasta la carpeta que contiene el archivo que creó.
Escriba el siguiente comando para compilar la aplicación.
dotnet build
Si la aplicación no tiene ningún error de compilación, se creará un archivo ejecutable con el nombre Factorial.exe.
Escriba el siguiente comando para calcular el factorial de 3:
dotnet run -- 3
El comando genera este resultado:
The factorial of 3 is 6.
Nota
Al ejecutar una aplicación en Visual Studio, puede especificar argumentos de la línea de comandos en la Página Depuración, Diseñador de proyectos.
Especificación del lenguaje C#
Para obtener más información, consulte la Especificación del lenguaje C#. La especificación del lenguaje es la fuente definitiva de la sintaxis y el uso de C#.