Main()과 명령줄 인수

Main 메서드는 C# 애플리케이션의 진입점입니다. (라이브러리와 서비스에는 Main 메서드가 진입점으로 필요하지 않습니다.) 애플리케이션이 시작될 때 Main 메서드는 호출되는 첫 번째 메서드입니다.

C# 프로그램에는 하나의 진입점만 있을 수 있습니다. Main 메서드가 있는 클래스가 둘 이상 있는 경우 StartupObject 컴파일러 옵션으로 프로그램을 컴파일하여 진입점으로 사용할 Main 메서드를 지정해야 합니다. 자세한 내용은 StartupObject(C# 컴파일러 옵션)를 참조하세요.

class TestClass
{
    static void Main(string[] args)
    {
        // Display the number of command line arguments.
        Console.WriteLine(args.Length);
    }
}

한 파일의 최상위 문을 애플리케이션의 진입점으로 사용할 수도 있습니다. 메서드와 Main 마찬가지로 최상위 문은 값을 반환하고 명령줄 인수에 액세스할 수도 있습니다. 자세한 내용은 최상위 문을 참조 하세요.

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;

개요

  • Main 메서드는 실행 가능한 프로그램의 진입점으로, 프로그램의 제어가 시작되고 끝나는 위치합니다.
  • Main은 클래스 또는 구조체 내부에 선언됩니다 Mainstatic이어야 하며 public일 필요는 없습니다. (이전 예제에서는 .의 private기본 액세스를 받습니다.) 은 묶을 class 수 있습니다 static.
  • Mainvoid, int, Task 또는 Task<int> 반환 형식을 가질 수 있습니다.
  • Main에서 Task 또는 Task<int>을 반환하는 경우에만 Main 선언에 async 한정자가 포함될 수 있습니다. 이는 특히 async void Main 메서드를 제외합니다.
  • Main 메서드는 명령줄 인수를 포함하는 string[] 매개 변수 사용 여부에 관계 없이 선언될 수 있습니다. Visual Studio를 사용하여 Windows 애플리케이션을 만드는 경우 매개 변수를 수동으로 추가하거나 GetCommandLineArgs() 메서드를 사용하여 명령줄 인수를 가져올 수 있습니다. 매개 변수는 0부터 시작하는 명령줄 인수로 읽힙니다. C 및 C++와 달리, 프로그램의 이름이 args 배열의 첫 번째 명령줄 인수로 처리되지 않지만, GetCommandLineArgs() 메서드의 첫 번째 요소입니다.

다음 목록은 유효한 Main 서명을 보여 줍니다.

public static void Main() { }
public static int Main() { }
public static void Main(string[] args) { }
public static int Main(string[] args) { }
public static async Task Main() { }
public static async Task<int> Main() { }
public static async Task Main(string[] args) { }
public static async Task<int> Main(string[] args) { }

앞의 예에서는 모두 public 접근자 한정자를 사용합니다. 이는 일반적이지만 필수는 아닙니다.

asyncTask, Task<int> 반환 형식을 추가하면 콘솔 애플리케이션을 시작해야 하고 비동기 작업을 Main에서 await해야 하는 경우에 프로그램 코드가 간소화됩니다.

Main() 반환 값

다음 방법 중 하나로 메서드를 정의하여 Main 메서드에서 int를 반환할 수 있습니다.

Main 메서드 코드 Main 서명
args 또는 await 사용 안 함 static int Main()
args 사용, await 사용 안 함 static int Main(string[] args)
args 사용 안 함 , await 사용 static async Task<int> Main()
argsawait 사용 static async Task<int> Main(string[] args)

Main의 반환 값을 사용하지 않는 경우 void 또는 Task를 반환하면 코드가 다소 단순해집니다.

Main 메서드 코드 Main 서명
args 또는 await 사용 안 함 static void Main()
args 사용, await 사용 안 함 static void Main(string[] args)
args 사용 안 함 , await 사용 static async Task Main()
argsawait 사용 static async Task Main(string[] args)

그러나 int 또는 Task<int>를 반환하면 프로그램이 실행 파일을 호출하는 다른 프로그램이나 스크립트에 상태 정보를 전달할 수 있습니다.

다음 예제에서는 프로세스의 종료 코드에 액세스할 수 있는 방법을 보여줍니다.

이 예제에서는 .NET Core 명령줄 도구를 사용합니다. .NET Core 명령줄 도구에 대해 잘 모르는 경우 이 시작 문서에서 알아볼 수 있습니다.

dotnet new console을 실행하여 새 애플리케이션을 만듭니다. Program.cs 에서 Main 메서드를 다음과 같이 수정합니다.

// Save this program as MainReturnValTest.cs.
class MainReturnValTest
{
    static int Main()
    {
        //...
        return 0;
    }
}

Windows에서 프로그램을 실행하는 경우 Main 함수에서 반환된 값은 환경 변수에 저장됩니다. 이 환경 변수는 배치 파일에서 ERRORLEVEL을 사용하거나 PowerShell에서 $LastExitCode를 사용하여 검색할 수 있습니다.

dotnet CLIdotnet build 명령을 사용하여 애플리케이션을 빌드할 수 있습니다.

다음으로 애플리케이션을 실행하고 결과를 표시하는 PowerShell 스크립트를 만듭니다. 다음 코드를 텍스트 파일에 붙여넣고 이 파일을 프로젝트가 포함된 폴더에 test.ps1로 저장합니다. PowerShell 프롬프트에 test.ps1을 입력하여 PowerShell 스크립트를 실행합니다.

코드에서 0을 반환하기 때문에 배치 파일이 성공했다고 보고합니다. 그러나 0이 아닌 값을 반환하도록 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 반환 값

Main에 대한 async 반환 값을 선언하면 컴파일러는 Main에서 비동기 메서드를 호출하기 위한 상용구 코드를 생성합니다. async 키워드를 지정하지 않으면 다음 예와 같이 해당 코드를 직접 작성해야 합니다. 예의 코드는 비동기 작업이 완료될 때까지 프로그램이 실행되도록 보장합니다.

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

    private static async Task<int> AsyncConsoleWork()
    {
        // Main body here
        return 0;
    }
}

이 상용구 코드는 다음으로 바뀔 수 있습니다.

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

    private static async Task<int> AsyncConsoleWork()
    {
        // main body here 
        return 0;
    }
}

Mainasync로 선언하면 컴파일러가 항상 올바른 코드를 생성한다는 이점이 있습니다.

애플리케이션 진입점에서 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();에 해당하는 코드를 내보냅니다.

참고 항목

예제에서 Main 메서드에 async 한정자를 사용하더라도 컴파일러는 동일한 코드를 생성합니다.

명령줄 인수

다음 방법 중 하나로 메서드를 정의하여 인수를 Main 메서드에 보낼 수 있습니다.

Main 메서드 코드 Main 서명
반환 값 없음, await 사용 없음 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)

인수가 사용되지 않는 경우 약간 더 간단한 코드를 위해 메서드 서명에서 args를 생략할 수 있습니다.

Main 메서드 코드 Main 서명
반환 값 없음, await 사용 없음 static void Main()
반환 값, await 사용 없음 static int Main()
반환 값 없음, await 사용 static async Task Main()
반환 값, await 사용 static async Task<int> Main()

참고 항목

Environment.CommandLine 또는 Environment.GetCommandLineArgs를 사용하여 콘솔 또는 Windows Forms 애플리케이션의 임의 지점에서 명령줄 인수에 액세스할 수 있습니다. Windows Forms 애플리케이션의 Main 메서드 서명에서 명령줄 인수를 사용하도록 설정하려면 Main의 서명을 수동으로 수정해야 합니다. Windows Forms 디자이너에서 생성된 코드는 입력 매개 변수 없이 Main을 만듭니다.

Main 메서드의 매개 변수는 명령줄 인수를 나타내는 String 배열입니다. 일반적으로 다음과 같이 Length 속성을 테스트하여 인수가 있는지 확인합니다.

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

args 배열은 null일 수 없습니다. 따라서 null 검사 없이 Length 속성에 액세스하는 것이 안전합니다.

Convert 클래스 또는 Parse 메서드를 사용하여 문자열 인수를 숫자 형식으로 변환할 수도 있습니다. 예를 들어 다음 문은 Parse 메서드를 사용하여 stringlong 숫자로 변환합니다.

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

Int64의 별칭을 지정하는 C# 형식 long을 사용할 수도 있습니다.

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

Convert 클래스 메서드 ToInt64를 사용하여 같은 작업을 수행할 수도 있습니다.

long num = Convert.ToInt64(s);

자세한 내용은 ParseConvert를 참조하세요.

명령줄 인수 구문 분석이 복잡할 수 있습니다. 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)
        {
            // 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.
    
  2. 시작 화면이나 시작 메뉴에서 Visual Studio 개발자 명령 프롬프트 창을 열고 만든 파일이 포함된 폴더로 이동합니다.

  3. 다음 명령을 입력하여 애플리케이션을 컴파일합니다.

    dotnet build

    애플리케이션에 컴파일 오류가 없으면 Factorial.exe라는 실행 파일이 만들어집니다.

  4. 다음 명령을 입력하여 3의 계승을 계산합니다.

    dotnet run -- 3

  5. 이 명령은 다음 출력을 생성합니다. The factorial of 3 is 6.

참고 항목

Visual Studio에서 애플리케이션을 실행할 경우 프로젝트 디자이너, 디버그 페이지에서 명령줄 인수를 지정할 수 있습니다.

C# 언어 사양

자세한 내용은 C# 언어 사양을 참조하세요. 언어 사양은 C# 구문 및 사용법에 대 한 신뢰할 수 있는 소스 됩니다.

참고 항목