다음을 통해 공유


자습서: 학습하면서 최상위 문을 사용하여 코드를 작성하는 아이디어 탐색

이 자습서에서는 다음 방법을 알아봅니다.

  • 최상위 문 사용을 제어하는 규칙을 알아봅니다.
  • 최상위 문을 사용하여 알고리즘을 탐색합니다.
  • 탐색을 재사용 가능한 구성 요소로 리팩터링합니다.

필수 구성 요소

.NET 6 이상을 실행하도록 컴퓨터를 설정해야 합니다. C# 컴파일러는 Visual Studio 2022 또는 .NET SDK부터 사용할 수 있습니다.

이 자습서에서는 Visual Studio 또는 .NET CLI를 포함하여 C# 및 .NET에 익숙하다고 가정합니다.

탐색 시작

최상위 문을 사용하면 프로그램의 진입점을 클래스의 정적 메서드로 만드는 데 필요한 복잡함을 피할 수 있습니다. 새 콘솔 애플리케이션의 일반적인 시작점은 다음 코드와 같습니다.

using System;

namespace Application
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
        }
    }
}

위의 코드는 dotnet new console 명령을 실행하고 새 콘솔 애플리케이션을 만든 결과입니다. 이러한 11개 줄에는 실행 코드 한 줄만 포함됩니다. 새로 도입된 최상위 문 기능을 활용하여 프로그램을 간소화할 수 있습니다. 이렇게 하면 이 프로그램에서 두 줄을 제외한 모든 줄을 제거할 수 있습니다.

// See https://aka.ms/new-console-template for more information
Console.WriteLine("Hello, World!");

중요하다

.NET 6용 C# 템플릿은 최상위 문 을 사용합니다. .NET 6으로 이미 업그레이드한 경우 애플리케이션이 이 문서의 코드와 일치하지 않을 수 있습니다. 자세한 내용은 새 C# 템플릿에서 최상위 문 생성 문서를 참조하세요.

.NET 6 SDK는 다음 SDK를 사용하는 프로젝트에 대한 암시적global using 지시문 집합도 추가합니다.

  • Microsoft.NET.Sdk
  • Microsoft.NET.Sdk.Web
  • Microsoft.NET.Sdk.Worker

이러한 암시적 global using 지시문에는 프로젝트 형식에 대한 가장 일반적인 네임스페이스가 포함됩니다.

자세한 내용은 "암시적인 using 지시문"에 대한 문서를 참조하세요.

이 기능은 새로운 아이디어를 간단하게 탐색할 수 있습니다. 스크립팅 시나리오에 최상위 문을 사용하거나, 탐색 목적으로 사용할 수 있습니다. 기본 사항이 작동하면 코드 리팩터링을 시작하고 빌드한 재사용 가능한 구성 요소에 대한 메서드, 클래스 또는 기타 어셈블리를 만들 수 있습니다. 최상위 문장은 빠른 실험과 초보자 가이드를 가능하게 합니다. 또한 실험에서 전체 프로그램으로의 원활한 경로를 제공합니다.

최상위 명령문은 코드 파일에 나타나는 순서대로 실행됩니다. 최상위 문은 애플리케이션의 한 소스 파일에서만 사용할 수 있습니다. 둘 이상의 파일에서 사용하는 경우 컴파일러에서 오류를 생성합니다.

매직 .NET 응답 머신 빌드

이 자습서에서는 임의 답변으로 "예" 또는 "아니요" 질문에 대답하는 콘솔 애플리케이션을 빌드해 보겠습니다. 기능을 단계별로 빌드합니다. 일반적인 프로그램의 구조에 필요한 의식보다는 작업에 집중할 수 있습니다. 그런 다음, 기능에 만족하면 애플리케이션을 적합하게 리팩터링할 수 있습니다.

좋은 시작점은 질문을 콘솔에 다시 쓰는 것입니다. 다음 코드를 작성하여 시작할 수 있습니다.

Console.WriteLine(args);

args 변수를 선언하지 않습니다. 최상위 문이 포함된 단일 소스 파일의 경우, 컴파일러는 args을 명령줄 인수로 인식합니다. 인수의 유형은 모든 C# 프로그램에서와 같이 string[]입니다.

다음 dotnet run 명령을 실행하여 코드를 테스트할 수 있습니다.

dotnet run -- Should I use top level statements in all my programs?

명령줄에서 -- 뒤의 인수가 프로그램에 전달됩니다. 콘솔에 인쇄된 args 변수의 유형을 볼 수 있습니다.

System.String[]

콘솔에 질문을 쓰려면 인수를 열거하고 공백으로 구분해야 합니다. WriteLine 호출을 다음 코드로 바꿉다.

Console.WriteLine();
foreach(var s in args)
{
    Console.Write(s);
    Console.Write(' ');
}
Console.WriteLine();

이제 프로그램을 실행하면 질문을 인수 문자열로 올바르게 표시합니다.

임의 답변으로 응답

질문을 에코한 후 임의의 대답을 생성하는 코드를 추가할 수 있습니다. 가능한 답변 배열을 추가하여 시작합니다.

string[] answers =
[
    "It is certain.",       "Reply hazy, try again.",     "Don’t count on it.",
    "It is decidedly so.",  "Ask again later.",           "My reply is no.",
    "Without a doubt.",     "Better not tell you now.",   "My sources say no.",
    "Yes – definitely.",    "Cannot predict now.",        "Outlook not so good.",
    "You may rely on it.",  "Concentrate and ask again.", "Very doubtful.",
    "As I see it, yes.",
    "Most likely.",
    "Outlook good.",
    "Yes.",
    "Signs point to yes.",
];

이 배열에는 긍정적인 답변 10개, 중립적인 답변 5개, 부정적인 답변 5개가 있습니다. 다음으로, 다음 코드를 추가하여 배열에서 임의 응답을 생성하고 표시합니다.

var index = new Random().Next(answers.Length - 1);
Console.WriteLine(answers[index]);

애플리케이션을 다시 실행하여 결과를 볼 수 있습니다. 다음과 같은 출력이 표시됩니다.

dotnet run -- Should I use top level statements in all my programs?

Should I use top level statements in all my programs?
Better not tell you now.

답변을 생성하는 코드에는 최상위 문에 변수 선언이 포함됩니다. 컴파일러에는 컴파일러에서 생성된 Main 메서드에 해당 선언이 포함됩니다. 이러한 변수 선언은 지역 변수이므로 static 한정자를 포함할 수 없습니다.

이 코드는 질문에 답변하지만 기능을 하나 더 추가해 보겠습니다. 질문 앱에서 답변에 대해 생각하는 것을 시뮬레이션하고 싶습니다. ASCII 애니메이션의 비트를 추가하고 작업하는 동안 일시 중지하여 이 작업을 수행할 수 있습니다. 질문을 에코하는 줄 다음에 다음 코드를 추가합니다.

for (int i = 0; i < 20; i++)
{
    Console.Write("| -");
    await Task.Delay(50);
    Console.Write("\b\b\b");
    Console.Write("/ \\");
    await Task.Delay(50);
    Console.Write("\b\b\b");
    Console.Write("- |");
    await Task.Delay(50);
    Console.Write("\b\b\b");
    Console.Write("\\ /");
    await Task.Delay(50);
    Console.Write("\b\b\b");
}
Console.WriteLine();

또한 소스 파일의 맨 위에 using 지시문을 추가해야 합니다.

using System.Threading.Tasks;

using 지시문은 파일의 다른 명령문이나 선언문 앞에 있어야 합니다. 그렇지 않으면 컴파일러 오류입니다. 프로그램을 다시 실행하고 애니메이션을 볼 수 있습니다. 이를 통해 더 나은 경험을 할 수 있습니다. 당신의 취향에 맞게 지연의 길이를 실험합니다.

앞의 코드는 공백으로 구분된 회전 선 집합을 만듭니다. await 키워드를 추가하면 컴파일러가 프로그램 진입점을 async 한정자가 있는 메서드로 생성하고 System.Threading.Tasks.Task반환하도록 지시합니다. 이 프로그램은 값을 반환하지 않으므로 프로그램 진입점은 Task반환합니다. 프로그램에서 정수 값을 반환하는 경우 최상위 문 끝에 return 문을 추가합니다. 이 return 문은 반환할 정수 값을 지정합니다. 최상위 문에 await 식이 포함된 경우 반환 형식은 System.Threading.Tasks.Task<TResult>됩니다.

미래를 위한 리팩터링

프로그램은 다음 코드와 같이 작성되어야 합니다.

Console.WriteLine();
foreach(var s in args)
{
    Console.Write(s);
    Console.Write(' ');
}
Console.WriteLine();

for (int i = 0; i < 20; i++)
{
    Console.Write("| -");
    await Task.Delay(50);
    Console.Write("\b\b\b");
    Console.Write("/ \\");
    await Task.Delay(50);
    Console.Write("\b\b\b");
    Console.Write("- |");
    await Task.Delay(50);
    Console.Write("\b\b\b");
    Console.Write("\\ /");
    await Task.Delay(50);
    Console.Write("\b\b\b");
}
Console.WriteLine();

string[] answers =
[
    "It is certain.",       "Reply hazy, try again.",     "Don't count on it.",
    "It is decidedly so.",  "Ask again later.",           "My reply is no.",
    "Without a doubt.",     "Better not tell you now.",   "My sources say no.",
    "Yes – definitely.",    "Cannot predict now.",        "Outlook not so good.",
    "You may rely on it.",  "Concentrate and ask again.", "Very doubtful.",
    "As I see it, yes.",
    "Most likely.",
    "Outlook good.",
    "Yes.",
    "Signs point to yes.",
];

var index = new Random().Next(answers.Length - 1);
Console.WriteLine(answers[index]);

위의 코드는 합리적입니다. 잘돼요. 그러나 재사용할 수는 없습니다. 이제 애플리케이션이 작동했으므로 다시 사용할 수 있는 부분을 꺼내야 합니다.

한 가지 후보는 대기 중인 애니메이션을 표시하는 코드입니다. 이 코드 조각은 메서드가 될 수 있습니다.

파일에서 로컬 함수를 만들어 시작할 수 있습니다. 현재 애니메이션을 다음 코드로 바꿉다.

await ShowConsoleAnimation();

static async Task ShowConsoleAnimation()
{
    for (int i = 0; i < 20; i++)
    {
        Console.Write("| -");
        await Task.Delay(50);
        Console.Write("\b\b\b");
        Console.Write("/ \\");
        await Task.Delay(50);
        Console.Write("\b\b\b");
        Console.Write("- |");
        await Task.Delay(50);
        Console.Write("\b\b\b");
        Console.Write("\\ /");
        await Task.Delay(50);
        Console.Write("\b\b\b");
    }
    Console.WriteLine();
}

앞의 코드는 main 메서드 내에 로컬 함수를 만듭니다. 해당 코드는 여전히 재사용할 수 없습니다. 따라서 해당 코드를 클래스로 추출합니다. utilities.cs 새 파일을 만들고 다음 코드를 추가합니다.

namespace MyNamespace
{
    public static class Utilities
    {
        public static async Task ShowConsoleAnimation()
        {
            for (int i = 0; i < 20; i++)
            {
                Console.Write("| -");
                await Task.Delay(50);
                Console.Write("\b\b\b");
                Console.Write("/ \\");
                await Task.Delay(50);
                Console.Write("\b\b\b");
                Console.Write("- |");
                await Task.Delay(50);
                Console.Write("\b\b\b");
                Console.Write("\\ /");
                await Task.Delay(50);
                Console.Write("\b\b\b");
            }
            Console.WriteLine();
        }
    }
}

최상위 문이 있는 파일에는 최상위 문 뒤의 파일 끝에 네임스페이스 및 형식이 포함될 수도 있습니다. 그러나 이 자습서에서는 애니메이션 메서드를 더 쉽게 재사용할 수 있도록 별도의 파일에 배치합니다.

마지막으로, 애니메이션 코드를 정리하여 일부 중복을 제거하려면 foreach 루프를 사용하여 animations 배열에 정의된 애니메이션 요소 집합을 반복할 수 있습니다.
리팩터링 후 전체 ShowConsoleAnimation 메서드는 다음 코드와 유사해야 합니다.

public static async Task ShowConsoleAnimation()
{
    string[] animations = ["| -", "/ \\", "- |", "\\ /"];
    for (int i = 0; i < 20; i++)
    {
        foreach (string s in animations)
        {
            Console.Write(s);
            await Task.Delay(50);
            Console.Write("\b\b\b");
        }
    }
    Console.WriteLine();
}

이제 전체 애플리케이션이 있으며 나중에 사용할 수 있게 재사용 가능한 부분을 리팩터링했습니다. 주 프로그램의 완성된 버전에 표시된 것처럼 최상위 문에서 새 유틸리티 메서드를 호출할 수 있습니다.

using MyNamespace;

Console.WriteLine();
foreach(var s in args)
{
    Console.Write(s);
    Console.Write(' ');
}
Console.WriteLine();

await Utilities.ShowConsoleAnimation();

string[] answers =
[
    "It is certain.",       "Reply hazy, try again.",     "Don’t count on it.",
    "It is decidedly so.",  "Ask again later.",           "My reply is no.",
    "Without a doubt.",     "Better not tell you now.",   "My sources say no.",
    "Yes – definitely.",    "Cannot predict now.",        "Outlook not so good.",
    "You may rely on it.",  "Concentrate and ask again.", "Very doubtful.",
    "As I see it, yes.",
    "Most likely.",
    "Outlook good.",
    "Yes.",
    "Signs point to yes.",
];

var index = new Random().Next(answers.Length - 1);
Console.WriteLine(answers[index]);

앞의 예제에서는 Utilities.ShowConsoleAnimation호출을 추가하고 using 지시문도 하나 더 추가합니다.

요약

최상위 문을 사용하면 새 알고리즘을 탐색하는 데 사용할 간단한 프로그램을 더 쉽게 만들 수 있습니다. 다른 코드 조각을 시도하여 알고리즘을 실험할 수 있습니다. 작동하는 기능을 알게 되면 코드를 더 쉽게 유지 관리할 수 있도록 리팩터링할 수 있습니다.

최상위 문은 콘솔 앱을 기반으로 하는 프로그램을 간소화합니다. 이러한 앱에는 Azure 함수, GitHub 작업 및 기타 작은 유틸리티가 포함됩니다. 자세한 내용은 최상위 문(C# 프로그래밍 가이드)참조하십시오.