Поделиться через


Main() и аргументы командной строки

Метод Main — это точка входа приложения C#. Когда приложение запускается, первым вызывается именно метод Main.

В программе на C# может существовать только одна точка входа. Если у вас есть несколько классов с методом Main, программу нужно компилировать с параметром компилятора StartupObject, чтобы указать, какой из методов Main будет использоваться в качестве точки входа. Дополнительные сведения см. в разделе StartupObject (параметры компилятора C#).
Ниже приведен пример, в котором первая строка, выполненная, будет отображать количество аргументов командной строки:

class TestClass
{
    static void Main(string[] args)
    {
        Console.WriteLine(args.Length);
    }
}

Инструкции верхнего уровня можно также использовать в одном файле в качестве точки входа для приложения. Так же, как Main и метод, операторы верхнего уровня также могут возвращать значения и получать доступ к аргументам командной строки. Дополнительные сведения см . в инструкциях верхнего уровня.
В следующем примере используется цикл foreach для отображения аргументов командной строки с помощью переменной args, а в конце программы возвращается код успешного выполнения (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;

Обзор

  • Метод Main — это точка входа для выполняемой программы. Это начальный и завершающий этапы управления программой.
  • Main должен быть объявлен внутри класса или структуры. Включающее class может быть static.
  • Аргумент Main должен иметь значение static.
  • Main может иметь любой модификатор доступа (кроме file).
  • Mainможет иметь voidтип , intTaskили Task<int> возвращаемый тип.
  • Если только Main возвращает Task или Task<int>, объявление Main может включать модификатор async. Это, в частности, исключает async void Main метод.
  • Метод Main может быть объявлен с параметром string[], который содержит аргументы командной строки, или без него. При использовании Visual Studio для создания приложений Windows можно добавить параметр вручную или использовать GetCommandLineArgs() метод для получения аргументов командной строки. Параметры считываются как аргументы командной строки, индексы которых начинаются с нуля. В отличие от C и C++, имя программы не рассматривается как первый аргумент командной строки в массиве args, но является первым элементом метода GetCommandLineArgs().

В следующем списке показаны наиболее распространенные Main объявления:

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) { }

В предыдущих примерах не указывается модификатор доступа, поэтому они неявно private по умолчанию. Это обычно, но можно указать любой явный модификатор доступа.

Совет

Добавление значений async и Task, а также типов возвращаемого значения Task<int> упрощает код программы, когда консольным приложениям требуется запустить и ожидать (await) асинхронные операции в Main.

Возвращаемые значения Main()

Вы можете возвратить int из метода Main, определив метод одним из следующих способов:

Main декларация Код метода Main
static int Main() Без использования args или await
static int Main(string[] args) С использованием args, без использования await
static async Task<int> Main() Без использования args, с использованием await
static async Task<int> Main(string[] args) С использованием args и await

Если значение, возвращаемое методом Main, не используется, возврат void или Task несколько упрощает код.

Main декларация Код метода Main
static void Main() Без использования args или await
static void Main(string[] args) С использованием args, без использования await
static async Task Main() Без использования args, с использованием await
static async Task Main(string[] args) С использованием args и await

Однако возврат int или Task<int> позволяет программе передавать информацию о своем состоянии другим программам и скриптам, которые вызывают исполняемый файл.

В следующем примере показано, как можно получить доступ к коду завершения для процесса.

В этом примере используются программы командной строки .NET Core. Если вы не знакомы с программами командной строки .NET Core, можете обратиться к этой статье по началу работы.

Создайте приложение, выполнив команду dotnet new console. Измените Main метод в Program.cs следующим образом:

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

Не забудьте сохранить эту программу как MainReturnValTest.cs.

При запуске программы в Windows значение, возвращаемое функцией Main, сохраняется в переменной среды. Эту переменную среды можно получить из пакетного файла с помощью ERRORLEVEL или в PowerShell с помощью $LastExitCode.

Для сборки приложения можно выполнить команду dotnet build.

Затем создайте скрипт PowerShell для запуска приложения и отображения результата. Вставьте следующий код в текстовый файл и сохраните его под именем test.ps1 в папке проекта. Запустите скрипт PowerShell, введя команду test.ps1 в командной строке PowerShell.

Так как код возвращает нулевое значение, пакетный файл сообщает об успехе. Но если изменить файл MainReturnValTest.cs, чтобы он возвращал ненулевое значение, и затем повторно скомпилировать программу, то при последующем выполнении скрипта PowerShell будет выдано сообщение об ошибке.

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

Значения, возвращаемые асинхронным методом main

При объявлении возвращаемого значения asyncкомпилятор создает стандартный Main код для вызова асинхронных методов в Main. Если ключевое async слово не указано, необходимо самостоятельно написать этот код, как показано в следующем примере. Код в примере гарантирует, что программа выполняется до завершения асинхронной операции:

class AsyncMainReturnValTest
{
    public static int Main()
    {
        return AsyncConsoleWork().GetAwaiter().GetResult();
    }

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

Этот стандартный код можно заменить следующими способами:

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

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

В обоих примерах основной текст программы находится в теле метода AsyncConsoleWork().

Преимущество объявления Main как async того, что компилятор всегда создает правильный код.

Если точка входа приложения возвращает Task или Task<int>, то компилятор создает новую точку входа, которая вызывает метод точки входа, объявленный в коде приложения. Предположим, что эта точка входа называется $GeneratedMain. В этом случае компилятор создает следующий код для этих точек входа:

  • static Task Main() приводит к тому, что компилятор формирует эквивалент private static void $GeneratedMain() => Main().GetAwaiter().GetResult();
  • static Task Main(string[]) приводит к тому, что компилятор формирует эквивалент private static void $GeneratedMain(string[] args) => Main(args).GetAwaiter().GetResult();
  • static Task<int> Main() приводит к тому, что компилятор формирует эквивалент private static int $GeneratedMain() => Main().GetAwaiter().GetResult();
  • static Task<int> Main(string[]) приводит к тому, что компилятор формирует эквивалент private static int $GeneratedMain(string[] args) => Main(args).GetAwaiter().GetResult();

Примечание.

Если бы в примерах использовался модификатор async метода Main, компилятор сформировал бы точно такой же код.

Аргументы командной строки

Вы можете передавать аргументы в метод Main, определив метод одним из следующих способов:

Main декларация Код метода Main
static void Main(string[] args) Без возвращаемого значения, без использования await
static int Main(string[] args) С возвращаемым значением, без использования await
static async Task Main(string[] args) Без возвращаемого значения, с использованием await
static async Task<int> Main(string[] args) С возвращаемым значением, с использованием await

Если аргументы не используются, можно пропустить args объявление метода для немного простого кода:

Main декларация Код метода Main
static void Main() Без возвращаемого значения, без использования await
static int Main() С возвращаемым значением, без использования await
static async Task Main() Без возвращаемого значения, с использованием await
static async Task<int> Main() С возвращаемым значением, с использованием await

Примечание.

Вы также можете использовать Environment.CommandLine или Environment.GetCommandLineArgs получать доступ к аргументам командной строки из любой точки в консоли или приложении Windows Forms. Чтобы включить аргументы командной строки в объявлении метода в Main приложении Windows Forms, необходимо вручную изменить объявление Main. Код, созданный конструктором Windows Forms, создает Main без входного параметра.

Параметр метода Main — это массив String, представляющий аргументы командной строки. Как правило, определить, существуют ли аргументы, можно, проверив свойство Length, например:

if (args.Length == 0)
{
    System.Console.WriteLine("Please enter a numeric argument.");
    return 1;
}

Совет

Массив args не может иметь значение NULL. Поэтому доступ к свойству Length можно получить без проверки значения NULL.

Строковые аргументы также можно преобразовать в числовые типы с помощью класса Convert или метода Parse. Например, следующая инструкция преобразует string в число long с помощью метода Parse:

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

Можно также использовать тип C# long, который является псевдонимом Int64:

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

Кроме того, можно использовать метод класса Convert, ToInt64:

long num = Convert.ToInt64(s);

Дополнительные сведения см. в разделах Parse и Convert.

Совет

Анализ аргументов командной строки может быть сложным. Рекомендуется использовать библиотеку System.CommandLine (в настоящее время в бета-версии), чтобы упростить процесс.

В следующем примере показано использование аргументов командной строки в консольном приложении. Приложение принимает один аргумент времени выполнения, преобразует аргумент в целое число и вычисляет факториал числа. Если не указано никаких аргументов, приложение выдает сообщение, поясняющее правильное использование программы.

Чтобы скомпилировать и запустить приложение из командной строки, выполните следующие действия.

  1. Вставьте следующий код в любой текстовый редактор и сохраните файл как текстовый файл с именем 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;
        }
    }
    

    В начале метода Main программа проверяет, были ли предоставлены входные аргументы, сравнивая длину аргумента args с 0, и отображает помощь, если аргументы не найдены.
    Если аргументы предоставляются (args.Length больше 0) программа пытается преобразовать входные аргументы в числа. Это приведет к возникновению исключения, если аргумент не является числом.
    После вычисления факториала (хранящегося в переменной result типа long) подробный результат выводится в зависимости от значения переменной result.

  2. В меню "Пуск" или "Пуск" откройте окно командной строки разработчика Visual Studio и перейдите в папку, содержащую созданный файл.

  3. Введите следующую команду для компиляции приложения.

    dotnet build

    Если для приложения не выдаются ошибки компиляции, создается исполняемый файл с именем Factorial.exe.

  4. Введите приведенную ниже команду для вычисления факториала числа 3:

    dotnet run -- 3

  5. Если 3 введено в командной строке в качестве аргумента программы, выходные данные считываются: The factorial of 3 is 6.

Примечание.

При выполнении приложения в Visual Studio аргументы командной строки можно указать на странице "Отладка" в конструкторе проектов.

Спецификация языка C#

Дополнительные сведения см. в спецификации языка C#. Спецификация языка является предписывающим источником информации о синтаксисе и использовании языка C#.

См. также