메인 함수

C#의 메인함수는 프로그램의 시작점이다. 

프로그램이 실행될 때 가장 먼저 실행되는 함수로 몇가지 조건을 가진다.

- 클래스 또는 구조체 내부에 선언한다.

- 메인함수는 반드시 static으로 선언되어야하며 클래스 또는 구조체가 static일 필요는 없다.

- 접근제한자는 public일 필요는 없다.

- 반환형은 void, int, Task, Task<int> 형을 가질 수 있다. (Task, Task<int> 의 경우 async 한정자 필요)

- 매개변수는 string[]을 가질 수 있다. 이 매개변수에는 명령어 인자가 포함된다.

 

선언

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 접근 제한자는 일반적으로 사용되는 것이며 필요조건은 아니다.)

반환형

메인 함수는 한정자나 매개변수의 상태에 따라 반환형을 선택할 수 있다.

//매개변수, await을 모두 사용하지 않음
static int Main()
static void Main()

//매개변수, awiat 모두 사용
static async Task<int> Main(string[] args)
static void Main(string[] args)

//매개변수를 사용하고 await만 사용하지 않음
static int Main(string[] args)
static aync Task Main()

//매개변수를 사용하지않고 await만 사용
static async Task<int> Main()
static async Task Main(string[] args)

 

메인 함수의 반환값을 통해 프로그램 실행 결과를 확인할 수 있다.

윈도우에서 프로그램이 실행되면 메인 함수에서 반환되는 모든 값이 환경 변수에 저장된다.

저장된 환경 변수는 배치 파일의 ERRORLEVEL 또는 PowerShell의 $LastExitCode를 사용하여 검색할 수 있다.

 

테스트

int 값 반환 확인

실행하면 0을 반환하도록 메인 함수를 만든다.

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

해당 스크립트가 위치한 폴더에서 PowerShell을 열어 스크립트를 실행시킨다.

dotnet run
if ($LastExitCode -eq 0) {
	Write-Host "Execution succeeded"
} else
{
	Write-Host "Execution Failed"
}
Write-Host "Return value = " $LastExitCode

비동기 메인 함수

메인 함수를 비동기로 선언하면 컴파일러는 항상 올바른 코드를 실행하는 이점이 있다.

프로그램의 진입점에서 Task 또는 Task<int>를 반환할때 컴파일러는 프로그램 코드에 선언된 진입점 메서드를 호출하는 새로운 진입점을 생성한다.

 

진입점의 이름을 $GeneratedMain이라고 할때 컴파일러는 이 진입점에 대해 다음과 같은 코드를 생성한다.

 

// 결과적으로 동일한 코드를 생성
static Task Main()
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()

static Task<int> Main(string[])
private static int $GeneratedMain(string[] args) => Main(args).GetAwaiter().GetResult();

 

테스트

async 반환값 확인

비동기 함수 호출을 하기 위해서 상용구 코드를 사용하거나 직접 await을 반환하는 메인함수를 만든다.

// boilerplate code
public static void Main()
{
	AsyncConsoleWork().GetAwaiter().GetResult();
}

// or
static async Task<int> Main(string[] args)
{
	return await AsncConsoleWork();
}

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

 

코드를 작성한 다음 동일하게 명령어를 입력해보면 결과를 확인할 수 있는데 이번에는 await으로 인한 동작이 추가된걸 확인할 수 있다.

 

 

명령문 인자

다음 방법들로 함수를 정의해서 메인 함수에 인자를 전달할 수 있다.

Main method code Main signature
No return value, no use of await static void Main(string[] args)
Return value, no use of await static int Main(string[] args)
No return value, uses await static async Task Main(string[] args)
Return value, uses await static async Task<int> Main(string[] args)

인자를 사용하지 않는 경우 더 간단하게 함수를 선언할 수 있다.

Main method code Main signature
No return value, no use of await static void Main()
Return value, no use of await static int Main()
No return value, uses await static async Task Main()
Return value, uses await static async TaskMint> Main()
   

또한 Environment.CommandLine 이나 Environment.GetCommandLineArgs를 통해서 콘솔이나 WinForms 응용 프로그램에서 어느 시점에나 인자에 접근할 수 있다. 명령문 인자를 사용할 수 있도록 하기 위해서는 수동으로 메인 함수를 수정해야한다. 

 

💡 메인 함수의 매개변수는 명령문 인자로 문자열 배열이다. 보통은 인자의 존재를 확인할때 문자열 속성인 Lenght 사용한다.

이때 문자열 배열은 null이 올 수 없기 때문에 null 검사하지 않고 Length로만 판단해도 안전하다.

 

문자열 인자는 Convert 클래스나 Parse 함수를 사용해서 숫자 형식으로 변환할 수 있다.

 

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

 

문자열을 정수로 변환하여 사용하는 예제

인자가 없는 경우 응용 프로그램은 프로그램의 올바른 사용법을 설명하는 메시지를 출력한다.

 

// ---How to using numeric argument---
// Factorial : 정수로 변환된 인자를 팩토리얼 계산후 반환
public class Functions
{
    public static long Factorial(int n)
    {
        if ((n < 0) || (n > 20))
        {
            return -1;
        }

        long tempResult = 1;
        for (int i = 1; i <= n; i++)
        {
            tempResult *= i;
        }
        return tempResult;
    }
}

class Program
{
    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;
    }
}

예제를 테스트 하기위해서 Developer Command Prompt를 사용한다.

시작 메뉴에서 커맨드 창을 실행시킨다.

(프롬프트창은 굳이 위 프로그램을 사용하지 않아도 된다.)

 

💡Command  명령어 : 경로 이동 cd <path>, 드라이브 변경하는방법 C:\>E:

 

스크립트 파일이 위치한 경로로 이동한 후 다음 명령어를 실행한다,

dotnet build

만약 응용 프로그램이 컴파일 오류가 없다면 해당 스크립트파일의 빌드 파일이 실행된다.

팩토리얼 함수가 잘 동작하는지 확인하기 위해서 인자를 전달해본다.

3의 인자를 전달했을때 3!의 계산 결과인 6이 잘 출력되는걸 확인할 수 있다.

 

728x90
반응형

'Program Language > C#' 카테고리의 다른 글

C# 비동기화 키워드 : async, await  (0) 2023.01.31
C# 클래스 추상화 키워드 : abstract  (0) 2023.01.25
테스트 환경  (0) 2023.01.17
.Net Framework  (0) 2023.01.17
C#  (0) 2023.01.17

C# 예제를 작성하고 테스트를 하기위한 IDE는 Visual Studio를 사용한다.

 

사용하는 버전은 Visual Studio 2022이며 프로젝트 템플릿은 .Net 환경의 Console App 을 사용한다,

 

 

프로젝트가 열리면 기본으로 Program.cs 스크립트가 만들어져있고 Hello World!를 출력하는 코드가 작성되어있다.

F5를 눌러서 콘솔창을 띄워서 해당코드를 실행시켜 볼 수 있다.

 

 

그런데 템플릿에 작성된 코드를 보면 뭔가 빠져있다는것을 알 수 있다.

원래 C# 에서는 코드가 실행되기 위해서 반드시 메인 함수가 있어야하고 이 함수 내부에서 호출이 되어야 실행이된다.

 

코드의 첫번째 라인에 있는 링크를 들어가보면 이러한 변경사항에 대한 공시 문서의 설명이 나온다.

.Net 6 부터 C# Console App 프로젝트 템플릿은 Program.cs 파일에 위처럼 코드를 생성하게 되며 이전 버전의 경우는 그대로 전체 코드를 생성한다. 

 

이전의 방식을 사용하고 싶은 경우 프로젝트 생성시 해당 옵션을 체크해준다.

 

최신 템플릿을 사용하지 않고 기존의 방식으로 코드가 뜨는걸 확인할 수 있다.

https://aka.ms/new-console-template

 

위 링크를 들어가보면 다른 방법으로도 템플릿을 설정할 수 있으며 암시적으로 사용중인 using의 경우도 수정할 수 있다.

 

공부가 목적이기 때문에 우선 생략된 코드가 없는 방식을 사용하기로 한다.

728x90
반응형

'Program Language > C#' 카테고리의 다른 글

C# 비동기화 키워드 : async, await  (0) 2023.01.31
C# 클래스 추상화 키워드 : abstract  (0) 2023.01.25
Main method  (0) 2023.01.19
.Net Framework  (0) 2023.01.17
C#  (0) 2023.01.17

마이크로소프트사에서 개발한 프로그래밍언어이다. 특정 프레임워크내에서 사용하도록 만들어졌으며 다루기 쉽고 편리한 기능들을 지원한다.

 

Feature

- .Net 프레임워크내에서 사용되는 언어이다.

- 다중 패러다임을 지원한다.

- C, C++, Java와 문법이 비슷하다.

- 자동으로 메모리를 관리한다.

- 모든 메서드와 변수는 클래스내에서 선언된다.

 

.Net Framework 정리글

 

Object-Oriented Programming

객체지향 프로그래밍

C# 은 모두 클래스 단위로 만들어지고 사용된다.

사용하려는 함수, 변수를 하나의 객체로 만들어 사용하는것이 특징이며 전역 변수나 전역 함수와 같은 방식은 허용되지 않으며 어디서든 사용하기 위한 함수나 변수를 선언하기 위해서는 정적 클래스를 선언하고 그 내부에 함수와 변수를 선언하고 해당 정적 클래스를 통해 접근해서 사용하는 방식을 권장한다.

 

Multi-Paradigm Programming

하나의 프로그래밍 언어에서 하나의 패러다임에 국한되지 않고 여러 가지 프로그래밍 패러다임을 지원하는 것을 의미한다. 이 패러다임이란 사고 방식이나 문제 해결을 위한 접근 방식 그리고 특정 언어의 디자인 패턴과 같은 것을 말한다,

* Paradigm : 어떤 분야에서의 일관된 이론적 모델이나 철학적 접근 방식을 말한다.

 

Structed Programming

구조적 프로그래밍은 선택 및 반복 그리고 블록 구조 및 서브루틴의 구조화된 제어 흐름을 광범위하게 사용하여 컴퓨터 프로그램의 명료성, 품질 및 개발 시간을 향상시키는 것을 목표로한다.

 

Imperative Programming

명령형 프로그래밍은 프로그램의 상태를 Statements를 사용해 변경시키는 것을 말하며 명령적 프로그래밍은 컴퓨터가 수행할 명령으로 구성된다. 프로그램의 예상 결과에 대한 높은 수준의 설명보다 단계별로 프로그램이 작동하는 방식을 설명하는데 중점을 둔다.

 

Object-Oriented Programming

객체 지향 프로그래밍은 데이터와 코드를 포함할 수 있는 객체의 개념을 기반으로 하는 프로그래밍 패러다임이다.

데이터는 필드의 형태이고 코드는 절차의 형태를 한다. 객체는 일반적으로 프로시저나 메서드가 붙어있고 그것들을 통해서 객체의 데이터에 접근하고 수정하는 형태를 가진다.

 

Event-Driven Programming

이벤트 기반 프로그래밍은 마우스 클릭, 키 입력같은 사용자 동작이나 센서 출력, 메시지 전달 등의 이벤트에 의해 프로그램의 흐름이 결정되는 방식이다.

 

Asnychronous Method Invocation

비동기 메서드 호출, 멀티스레드 컴퓨터 프로그래밍에서 호출된 코드가 끝나기를 기다리는 동안 다른 호출이 차단되지 않는 설계 패턴이다. 응답이 도착하면 호출 스레드가 알려지고 응답에 대한 폴링은 되지 않는다.

* Polling

스레드에 플래그를 놓아 값이 준비되면 플래그를 메인 프로그램에 전달해주는 것을 말한다. 메인 프로그램에서는 주기적으로 스레드에 값이 준비되었는지 확인하는 작업이 필요하다.

 

Functional Programming

함수형 프로그래밍은 상태와 가변 데이터를 멀리하는 프로그래밍 패러다임이다. 자료처리를 수학적 함수의 계산처럼 취급한다.

 

Generic Programming

범용 프로그래밍은 하나의 코드를 통해 다양한 타입을 처리하는 것을 말한다.

 

Reflective Programming

Reflection을 활용하는 프로그래밍 패러다임이다.

* Reflection

런타임 시점에서 자신의 구조와 행위를 관리하고 수정할 수 있는 프로세스를 뜻한다. 

행위 관리(Type Introspection) 은 런타임에서 객체의 타입을 결정할 수 있는 능력을 의미한다.

 

Concurrent Computing

동시 컴퓨팅, 프로세스에 대해 별도의 실행 지점 또는 제어 스레드가 있는 시스템 속성이다. 동시 시스템은 다른 연산이 완료될 때까지 기다리지 않고 연산이 진행될 수 있는 시스템이다.

모듈러 프로그래밍의 한 형태로 전체적인 계산은 동시에 실행될 수 있는 서브 컴퓨터에 반영된다.

 

Garbage Collection

C#이 다른 언어들과 가장 큰 차이를 보이는 부분은 메모리 관리에 있다. 메모리는 GC(Galbage Collector)를 통해서 관리된다. GC는 동적으로 할당된 메모리에 대해서 특정 시점에 특정 조건을 통해서 더 이상 사용되지 않는다고 판단되는 할당된 메모리를 해제하는 작업을 한다. 

 

GC는 사용자로 하여금 메모리 관리에 신경쓰지 않아도 되는 편의성을 제공하지만 동시에 메모리에 대해서는 사용자가 관리할 수 없다는 단점도 가지고 있다. 

 

Static

C#에서는 모든 메서드나 변수의 선언은 클래스 내부에서 가능하다. 즉 다른 언어처럼 전역으로 선언하고 어디서든 호출할 수 있게 만드는게 불가능하다.

애초에 C#은 어떤 클래스든 다른 클래스에서 호출하는것이 가능하기 때문에 전역으로 선언이 사용될 필요가 없게 되는데 이때 매번 인스턴스를 생성하는게 불편하다면 정적 클래스를 생성하고 그 내부에 메서드와 변수를 선언하여 사용하면 된다.

 

 

 

728x90
반응형

'Program Language > C#' 카테고리의 다른 글

C# 비동기화 키워드 : async, await  (0) 2023.01.31
C# 클래스 추상화 키워드 : abstract  (0) 2023.01.25
Main method  (0) 2023.01.19
테스트 환경  (0) 2023.01.17
.Net Framework  (0) 2023.01.17

+ Recent posts