Compartir a través de


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#). En el ejemplo siguiente se muestra el número de argumentos de la línea de comandos como su primera acción:

class TestClass
{
    static void Main(string[] args)
    {
        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. En el ejemplo siguiente se usa un foreach bucle para mostrar los argumentos de la línea de comandos mediante la args variable y al final del programa se devuelve un código correcto (0):

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;

A partir de C# 14, los programas pueden ser aplicaciones basadas en archivos, donde un único archivo contiene el programa. Las aplicaciones basadas en archivos se ejecutan con el comando dotnet run <file.cs>o se usa la #!/usr/local/share/dotnet/dotnet run directiva como primera línea (solo shells de Unix).

Información general

  • El Main método es el punto de entrada de un programa ejecutable; es donde se inicia y finaliza el control de programa.
  • Main debe declararse dentro de una clase o estructura. La class envolvente puede ser static.
  • Main debe ser static.
  • Main puede tener cualquier modificador de acceso (excepto file).
  • Main puede tener un tipo de valor devuelto void, int, Task o Task<int>.
  • Si y solo si Main devuelve un Task o un Task<int>, la declaración de Main puede incluir el modificador async. Esta regla excluye específicamente un async void Main método .
  • El método Main se puede declarar con o sin un parámetro string[] 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 de la args matriz, pero es el primer elemento del GetCommandLineArgs() método.

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. 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 por 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) Usa args , pero no await
static async Task<int> Main() Usa await , pero no args
static async Task<int> Main(string[] args) Se usan args y await

Si no se usa el valor devuelto de Main , devuelve void o Task permite un código 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) Usa args , pero no await
static async Task Main() Usa await , pero no args
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:

class MainReturnValTest
{
    static int Main()
    {
        //...
        return 0;
    }
}

Recuerde guardar este programa como MainReturnValTest.cs.

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 de la CLI de dotnetdotnet build.

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 escribiendo test.ps1 en PowerShell.

Dado que el código devuelve cero, el archivo por lotes informa de un éxito. Sin embargo, si cambia MainReturnValTest.cs para devolver un valor distinto de cero y, a continuación, volver a compilar el programa, la ejecución posterior del script de PowerShell notifica 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:

class Program
{
    static async Task<int> Main(string[] args)
    {
        return await AsyncConsoleWork();
    }

    private static async Task<int> AsyncConsoleWork()
    {
        return 0;
    }
}

En ambos ejemplos el cuerpo principal del programa está dentro del cuerpo del método AsyncConsoleWork().

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 de private static void $GeneratedMain() => Main().GetAwaiter().GetResult();
  • static Task Main(string[]) hace que el compilador emita el equivalente de private static void $GeneratedMain(string[] args) => Main(args).GetAwaiter().GetResult();
  • static Task<int> Main() hace que el compilador emita el equivalente de private static int $GeneratedMain() => Main().GetAwaiter().GetResult();
  • static Task<int> Main(string[]) hace que el compilador emita el equivalente de private 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 devuelve ningún valor o await
static int Main(string[] args) Devuelve un valor, pero no usa await
static async Task Main(string[] args) Usa await pero no devuelve un valor
static async Task<int> Main(string[] args) Devolver un valor y usar await

Si no se utilizan los argumentos, puede omitir args de la declaración del método para un código ligeramente más sencillo.

Declaración Main Código del método Main
static void Main() No devuelve ningún valor o await
static int Main() Devuelve un valor, pero no usa await
static async Task Main() Usa await pero no devuelve un valor
static async Task<int> Main() Devuelve un valor y 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 es posible usar el tipo long de C#, cual es un alias de Int64.

long num = long.Parse(args[0]);

También puede usar el método Convert de la clase ToInt64 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 terminal, siga estos pasos:

  1. 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)
        {
            if (args.Length == 0)
            {
                Console.WriteLine("Please enter a numeric argument.");
                Console.WriteLine("Usage: Factorial <num>");
                return 1;
            }
    
            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;
            }
    
            long result = Functions.Factorial(num);
    
            if (result == -1)
                Console.WriteLine("Input must be >= 0 and <= 20.");
            else
                Console.WriteLine($"The Factorial of {num} is {result}.");
    
            return 0;
        }
    }
    

    Al principio del Main método, el programa comprueba si no se proporcionaron argumentos de entrada que comparan la longitud del args argumento con 0 y muestra la ayuda si no se encuentra ningún argumento.
    Si se proporcionan argumentos (args.Length es mayor que 0), el programa intenta convertir los argumentos de entrada en números. En este ejemplo se produce una excepción si el argumento no es un número.
    Una vez calculado el factorial (almacenado en result de la variable de tipo long), el resultado detallado se imprime en función de la variable result.

  2. 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ó.

  3. Para compilar la aplicación, escriba el siguiente comando:

    dotnet build

    Si la aplicación no tiene errores de compilación, se crea un archivo binario denominado Factorial.dll .

  4. Escriba el siguiente comando para calcular el factorial de 3:

    dotnet run -- 3

  5. Si se escribe 3 en la línea de comandos como argumento del programa, la salida lee: 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#.

Vea también