extern

'외부의'라는 뜻을 가지는 External의 약자로 외부에 선언된 함수 또는 객체임을 명시하는 역할을 한다.

이때 외부란 C# 코드 이외의 언어로 작성된 코드를 뜻하며 DLL이나 C/C++ 등으로 작성된 함수를 말한다.

이런 외부에서 작성된 코드 즉, C# 및. Net 프레임 워크에서 사용되지 않는 코드 다시 말해서 CLR에서 관리되지 않는 코드를 unmanaged code라고 하는데 이러한 unmanaged code를 불러오기 위해서는 interop 기술이 필요하다.

 

Interop 정리글

 

간략하게 Interop은 다른 언어나 플랫폼에서 작성된 코드를 호출하거나 받는 기술로 COM, P/Invoke, C++/CLI 등이 대표적으로 있는데 extern 키워드는 이러한 함수나 객체가 외부의 것임을 나타내는 역할을 한다.

 

일반적으로 C#에서 많이 사용하는 P/Invoke 방식은 DllImport arttribute와 함께 사용한다.

이 경우 메서드는 반드시 static으로 선언되어야 한다.

// Microsoft AVI File support library
[DllImport("avifil32.dll")] // Interop, P/Invoke
private static extern void AVIFileInit();

 

extern alias

.Net 어셈블리에서 다른 버전의 동일한 어셈블리의 참조가 필요한 경우에 사용할 수 있다.

일반적으로 .Net 프로젝트에서 어셈블리의 참조는 using이나 Imports를 사용하여 참조하는데 만약 서로 다른 버전의 어셈블리를 참조하는 경우에는 컴파일러가 어떤 버전을 사용해야 하는지 구분이 필요하기 때문에 이런 경우 extern alias 키워드를 사용한다.

 

동일한 어셈블리를 버전별로 참조하기 위해서는 각각의 어셈블리를 특정시킬 수 있도록 만드는 작업이 필요하다.

특정시키는 방법으로는 각 어셈블리의 별칭을 지정하는 방법과 이름을 변경하는 방법이 있다.

 

Alias

어셈블리의 별칭을 지정하는 방법은 대표적으로 두 가지 방법이 있다.

 

1. Visual Studio 

비주얼 스튜디오의 솔루션 탐색기에서 별칭을 수정할 수 있다.

Assembly > 우클릭 속성 > Aliases 수정

2. 프롬프트 창

프롬프트에서 어셈블리에 별칭을 부여할 수 있다.

/r:GridV1=grid.dll
/r:GridV2=grid20.dll

 

각각의 어셈블리에 외부에서 사용할 별칭 GridV1과 GridV2가 지정된다.

 

이렇게 별칭을 지정해 주면 extern 키워드를 사용하여 별칭을 참조하면 동일한 어셈블리를 구분해서 참조가 가능해진다.

extern alias GridV1;
extern alias GridV2;
// can using namespace
using Class1V1 = GridV1::Namespace.Class1;
using Class1V2 = GridV2::Namespace.Class1;

 

Name

별칭을 지정하지 않고 이름을 변경하는 방법으로도 참조가 가능하다.

비주얼 스튜디오에서 별칭을 수정했던 설정창을 다시 켜보면 상단에 이름 속성을 확인할 수 있다.

이름을 사용하기 위해서는 별칭이 지정되지 않아야 하므로 별칭을 지우고 이름을 수정한다.

 

그 후에 C#에서 Type.GetType 메서드를 사용하면 어셈블리에서 Type을 가져올 수 있는데 이때 어셈블리의 전체 이름을 사용하여 Type을 가져오면 해당 어셈블리를 특정해서 참조할 수 있게 된다.

Type myType = Type.GetType("MyNamespace.MyType, MyAssembly");

 

728x90
반응형

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

Interoperability  (0) 2023.02.02
Managed, Unmanaged, Native Code  (0) 2023.02.02
C# 키워드 : delegate, event, action  (0) 2023.01.31
C# 상수 키워드 : const  (0) 2023.01.31
C# 비동기화 키워드 : async, await  (0) 2023.01.31

delegate

C/C++에는 함수를 가리키는 함수 포인터가 있다. 이를 사용하면 함수를 인수로 전달하거나 함수를 반환하는 등 다양한 방식으로 함수를 조작할 수 있는데 C#에서는 포인터를 직접적으로 사용할 수 없다. 그래서 C#에서 함수 포인터를 대신하는 개념으로 메서드를 참조하는 형식의 변수를 선언할 수 있도록 delegate를 사용한다.

 

delegate는 함수 포인터와 비슷한 개념으로 메서드에 대한 참조를 저장하여 메서드를 인수로 전달하거나 메서드를 반환하는 등의 작업을 수행할 수 있다. 메서드 자체를 하나의 변수로 다룰 수 있기 때문에 코드 자체를 참조하는 개념으로 볼 수 있다. 

선언

delegate void DelegateDefault();
delegate int DelegateReturn();
delegate int DelegateReturnParam(int x, int y);

static void Main(string[] args)
{
	DelegateDefault delegateDefault = new DelegateDefault(Print_1);
	DelegateReturn delegateReturn = new DelegateReturn(Print_2);
	DelegateReturnParam delegateReturnParam = new DelegateReturnParam(Print_3);

	delegateDefault();
	int result = delegateReturn();
	int result_2 = delegateReturnParam(1, 2);
}

static void Print_1()
{
	Console.WriteLine("Print_1");
}

static int Print_2()
{
	int num = 2;
	Console.WriteLine("Print_Out" + num);
	return num;
}

static int Print_3(int x, int y)
{
	int sum = x + y;
	Console.WriteLine("Print_Out" + sum);
	return sum;
}

선언된 델리게이트는 동일한 형식으로 선언된 메서드의 참조만 가능하다. 델게이트를 호출하면 참조중인 메서드를 호출하게 된다.

 

delegate chain

또한 델리게이트는 += 연산자를 통해서 동시에 여러 메서드를 참조할 수 있다.

delegate void DelegateChain();
DelegateChain delegateChain;
void Main(string[] args)
{
    delegateChain += Print_1;
    delegateChain += Print_2;
    delegateChain += Print_3;

	// ?.Invoke()를 사용하면 delegateChai이 null인 경우에 에러가 발생하는걸 방지할 수 있다.
    delegateChain?.Invoke();
    
    delegateChain -= Print_3;
    delegateChain -= Print_2;
    delegateChain -= Print_1;
}

static void Print_1() { }
static void Print_2() { }
static void Print_3() { }

참조중인 메서드 중에서 참조를 해제하려면 -= 연산자를 사용하면된다.

 

Anonymouse method call

델리게이트 체인을 활용해서 익명 메서드 호출도 가능하다.

void Main(string[] args)
{
    delegateChain += Print_1;
    delegateChain += Print_2;
    delegateChain += Print_3;
    delegateChain += delegate ()
    {
    	Console.WriteLine();
    };

    delegateChain?.Invoke();
    
	~
}

익명 메서드는 일회성으로 사용될 코드를 간단하게 작성할 때 주로 사용되며 특히 해당 코드가 특별한 용도를 제공하지 않거나 재사용될 필요가 없는 경우에 사용된다.

 

delegate는 대표적으로 이벤트 처리, 비동기 처리, 콜백에 사용된다.

 

Event

프로그래밍에서 이벤트는 어떤 특정한 조건이나 상황이 발생했을 때 이를 감지하고 처리하는 기능을 의미한다.

예를 들어 마우스 클릭, 키보드 입력 등이 이벤트이다. 이벤트 기반 프로그래밍(Event-driven programming)은 이러한 상황에서 반응하듯이 특정한 기능을 수행시키는 이벤트 기반으로 만드는 방식을 말하며 코드와의 상호작용으로 객체 간의 통신을 쉽게하고 객체의 라이프 사이클과 관련된 처리를 간편하게 할 수 있다.

 

Event Subscribe

이벤트 구독

일반적으로 이벤트를 다룰때 이벤트가 발생할때 동작시킬 기능에 해당하는 메서드의 할당과 참조는 외부에서 하더라도 이벤트의 발동은 델리게이트를 선언한 클래스 내에서 하는것이 권장된다.

 

외부에서 delegate에 메서드를 참조시키는걸 Subscribe, 참조한 메서드를 제거하는걸 Unsubscribe 라고 한다.

이렇게 외부에서 메서드를 참조하는 클래스를 Subscriber Class(구독자 클래스), 델리게이트가 선언된 클래스를 Publisher Class(게시자 클래스)라고 부른다.

 

public delegate MyDelegate();
// 게시자 클래스
public class MyPublisher
{
	// 델리게이트
	public MyDelegate MyEvent;
    public void OnEvent()
    {
    	MyEvent?.Invoke();
    }
}

// 구독자 클래스
public class MySubscriber
{
	private Publisher publisher = new Publisher();
	public void Subscirbe()
    {
    	// 구독
    	publisher.MyEvent += SomeMethod; 
    }
    
    public void UnSubscribe()
    {
    	// 해지
 		publicsher.MyEvent -= SomeMethod;
    }
    
    public void SomeMethod(){} 
}

 

event keyword

델리게이트를 이벤트 목적으로 사용할때 event 키워드를 사용한다.

event 키워드를 통해서 delegate가 선언되면 해당 델리게이트는 외부 클래스에서 실행이 불가능하게 된다.

따라서 외부 클래스는 이벤트를 구독과 해지만 가능하며 이벤트의 호출은 선언된 클래스 내부 오직 한곳에서만 일어나기 때문에 안전하게 사용할 수 있게 된다.

 

선언

class EventListner
{
    // 구독할 델리게이트 
    public delegate void EventHandler();
    // event를 통해서 MyEvent는 내부에서만 호출 가능해진다.
    public event EventHandler MyEvent;

    public void OnMyEvent()
    {
        // ? : EventName null check
        EventName?.Invoke();
    }
}

class SubscriberClass
{
	EventLister listner = new EventListenr();
    public void Subscribe()
    {
    	listner.MyEvent += SomeMethod
        // Cannot Call delegate
        lister.MyEvent?.Invoke();
    }
    
    public void SomeMethod(){}
}

 

event 제한자로 선언된 delegate를 외부 클래스에서 직접 호출을 시도하면 에러가 발생한다.

따라서 더 안전하게 이벤트를 구현할 수 있게 해주는 키워드라 할 수 있다.

 

Async

delegate의 비동기 작업은 일반적으로 멀티스레딩을 구현할 때 사용된다. 델리게이트를 통해서 메서드의 실행을 다른 스레드에게 위임하여 해당 스레드에서 비동기적으로 작업을 처리하고, 작업이 완료되면 해당 스레드가 호출한 스레드에게 결과를 알려준다. 이 작업 방식은 보통 결과를 필요로 하지 않는 작업을 빠르고 효율적으로 처리하기 위해서 사용한다.

 

보통 BeginInvoke()와 EndInvoke() 메서드를 활용해서 비동기를 구현한다.

* BeginInvoke : 해당 작업을 다른 스레드에서 비동기적으로 실행

* EndInvoke : 해당 작업이 완료되었는지 확인 후 결과를 반환

 

public delegate int AsyncMethodDelegate(int x, int y);

public class Calculator
{
    public int Add(int x, int y)
    {
        return x + y;
    }

	// Add 메서드를 비동기적으로 실행
    public void AddAsync(int x, int y, AsyncCallback callback)
    {
        AsyncMethodDelegate asyncMethod = new AsyncMethodDelegate(Add);
        // 작업이 종료되면 callback
        asyncMethod.BeginInvoke(x, y, callback, null);
    }
}

public class Program
{
    static void Main(string[] args)
    {
        Calculator calculator = new Calculator();
        AsyncCallback callback = new AsyncCallback(CalculateCompleted);

        calculator.AddAsync(1, 2, callback);
		
        Console.ReadLine();
    }
	
    // callback 호출 함수
    static void CalculateCompleted(IAsyncResult ar)
    {
        AsyncResult result = (AsyncResult)ar;
        AsyncMethodDelegate asyncMethod = (AsyncMethodDelegate)result.AsyncDelegate;

        int resultValue = asyncMethod.EndInvoke(ar);
        Console.WriteLine("Result: " + resultValue);
    }
}

 

Callback Function

콜백 함수는 다른 함수에서 인자로 전달되어 실행되는 함수를 말한다.

일반적으로 다른 함수의 작업이 완료된 후 호출된다.

 

만약 비동기적으로 실행되는 작업이 있을 때 해당 작업이 완료된 후 특정 동작을 실행시키고 싶다고 할때 여기서 콜백 함수를 사용할 수 있다. 비동기 작업을 수행하는 함수는 작업이 완료되면 콜백 함수를 호출하여 완료된 작업에 대한 처리를 수행하게 된다. 

 

콜백 함수는 함수 포인터(delegate)나 람다식 등의 방식으로 전달될 수 있으며 주로 이벤트 처리나 비동기 처리 등에서 사용된다.

 

EventHandler가 대표적인 콜백 함수라 볼 수 있다.

// 버튼 클릭 이벤트 처리를 위한 콜백 함수
private void Button_Click(object sender, EventArgs e)
{
    // 버튼이 클릭되었을 때 실행될 코드
}

// 이벤트 핸들러 등록을 위한 코드
button1.Click += new EventHandler(Button_Click);

버튼이 클릭되면 호출되는 Button_Click 메서드가 콜백 함수로 button1.Click 이벤트에 등록되어 클릭 이벤트가 발생하면 해당 콜백 함수가 실행되는 구조이다. 이렇게 delegate를 사용하여 콜백 함수를 등록함으로써 이벤트 처리와 같이 비동기적인 작업을 보다 효율적으로 처리할 수 있다.

 

Built-in delegate

C#의 내장형 delegate로 일반화된 형태의 델리게이트를 말한다.

매번 델리게이트를 선언하거나 만들 필요 없이 메서드를 매개변수로 전달하고 반환 값을 받을 수 있도록 하는것이 목적이다.

Action

Action은 C#의 내장 델리게이트 중 하나이다. 반환값이 없는 메서드를 참조할 수 있는 타입으로 매개변수를 받아서 반환값이 없는 메서드를 참조하는 기능을 한다.

Func

Func 또한 내장 델리게이트 중 하나로 입력 인자와 반환 값이 있는 일반적인 델리게이트 유형으로 반환 값을 가지는 메서드를 참조할 때 사용한다.

 

단순히 메서드를 전달 또는 메서드를 전달하고 반환 값을 받는 경우에는 Action이나 Func를 사용하는것이 코드를 간소화할 수 있다.

// Action을 사용하여 메서드를 매개변수로 전달하는 예시
public void PrintMessage(Action<string> messageAction)
{
    messageAction("Hello, world!");
}

// 메서드를 Action으로 전달하고 실행
PrintMessage(message => Console.WriteLine(message)); // "Hello, world!" 출력

// delegate를 쓴경우
public delegate void MessageDelegate(string message);	// 델리게이트 생성부터 필요
public void PrintMessage(MessageDelegate messageDelegate)
{
    messageDelegate("Hello, world!");
}

// 메서드를 delegate로 전달하고 실행
PrintMessage(message => Console.WriteLine(message)); // "Hello, world!" 출력


//==============================================================================



// Func을 사용하여 메서드를 매개변수로 전달하고 반환 값을 받는 예시
public int GetStringLength(Func<string, int> lengthFunc, string str)
{
    return lengthFunc(str);
}

// 메서드를 Func으로 전달하고 반환 값을 받습니다.
int strLength = GetStringLength(str => str.Length, "Hello"); // strLength에 5가 저장됩니다.


// delegate를 쓴경우
public delegate int LengthDelegate(string str);
public int GetStringLength(LengthDelegate lengthDelegate, string str)
{
    return lengthDelegate(str);
}

// 메서드를 delegate으로 전달하고 반환 값을 받습니다.
int strLength = GetStringLength(str => str.Length, "Hello"); // strLength에 5가 저장됩니다.

불필요한 delegate의 선언부를 줄일 수 있게 된다..

 

728x90
반응형

const

상수라는 뜻을가지는 Constant에서 따온 키워드이다.

상수란 프로그래밍에서 변하지 않는 값을 의미하는데 한번 값이 정해지면 프로그램이 실행되는 동안 그 값은  항상 일정하다. 컴파일 타임에 값이 결정되므로 런타임 시 메모리를 사용하지 않게 되어 상수를 사용하면 메모리 사용을 줄일 수 있다.

 

public class Program
{
	public static void Main(string[] args)
    {
    	const int A = 10;
        A = 10; // Compiler Error CS0131
    }
}

 

const 키워드로 선언된 변수는 상수로 취급되기 때문에 값을 재할당하면 컴파일 에러가 뜬다. 따라서 상수는 코드 흐름에서도 바뀔 필요가 없고 일정하게 사용될 값이 필요할 때 사용한다.

 

literal const

리터럴 상수 또한 상수와 마찬가지로 변하지 않는 값을 표현할 때 사 용는데 두 개념에는 약간의 차이가 있다.

상수는 const 예약어를 사용해서 변수형태로 선언되고 컴파일 시간에 값이 결정되어 프로그램 중에 값이 변경되지 않는 것이라면 리터럴 상수는 컴파일러가 코드에서 직접 사용할 수 있는 값을 의미한다. 예를 들어서 0, 1, 2, 3 등이 모두 정수형 리터럴 상수로 변수나 상수가 아니면서 프로그램 실행 중에도 변경할 수 없는 값이다.

 

// 상수 PI
const double PI = 3.14159265358979;
// 숫자 리터럴 상수
double radius = 3.0;
// 문자 리터럴 상수
char c = 'C';
// 문자열 리터럴 상수
string str = "Str";

리터럴 상수에는 숫자뿐만 아니라 문자 또한 포함된다.

즉 코드 상에서 선언되지 않았으면서 변수에 할당이 가능한 모든 값을 리터럴 상수라고 할 수 있다.

728x90
반응형

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

C# 외부 코드 사용 키워드 : extern  (1) 2023.01.31
C# 키워드 : delegate, event, action  (0) 2023.01.31
C# 비동기화 키워드 : async, await  (0) 2023.01.31
C# 클래스 추상화 키워드 : abstract  (0) 2023.01.25
Main method  (0) 2023.01.19

async

메서드, 람다 표현식 또는 무명 메서드를 비동기로 특정할 수 있다.

메서드나 표현식에 async 제한자가 붙으면 비동기식 메서드라고 한다.

 

public async Task<T> ExampleMethodAsync()
{
	string contents = await NetworkManager.GetData(url);
}

 

async만 사용한다고 메서드가 비동기로 작동하는 것은 아니며 첫 번째 await 표현식을 만날 때까지 동기적으로 실행된다. 

await의 동작이 완료될 때까지 메서드는 대기하게 되고 메서드 호출자는 다음 동작을 진행하게 된다.

 

async 키워드로 선언된 비동기 메서드가 await 표현식이나 구문이 포함되어있지 않으면 컴파일러는 경고를 띄우게 된다.

비동기 메서드의 반환형은 Task <T>, Task(void) 형태로 정의되고 return T와 같이 해당 타입만 반환한다.

컴파일러는 return T을 자동으로 Task <T>로 변환한다. 특히 async 메서드는 이벤트핸들러를 위해 void의 반환을 허용하고 있다.

 

awiat은 일반적으로 Task 또는 Task <T> 객체와 함께 사용되는데 Task 이외에 awaitable 클래스도 함께 사용할 수 있다.

* awaitable : GetAwaiter() 메서드를 갖는 클래스

 

 

About sync and async

 

Example

    class Program
    {
        public static void Main(string[] args)
        {
            TaskTest(10);
            Console.WriteLine("============Call Main============");

            Console.ReadLine();
        }
        private static async void TaskTest(int count)
        {
            Console.WriteLine("============Call Task1============");

            for (int i = 0; i < count; i++)
            {
                var message = String.Format("Count {0}", i);
                Console.WriteLine(message);
                await Task.Delay(1000);
            }

            Console.WriteLine("============End Task1============");
        }
    }

Main 함수가 실행되면서 TaskTest를 호출한다.

그리고 곧이어 비동기적으로 Main 함수의 다음 코드가 실행되면서 TaskTest의 다음 동작이 진행된다.

 

 메인함수 또한 비동기로 정의하여 사용할 수 있다.

    class Program
    {
        public static async Task Main(string[] args)
        {
            await TaskTest(10);
        }
        private static async Task TaskTest(int count)
        {
            Console.WriteLine("============Call Task1============");

            for (int i = 0; i < count; i++)
            {
                var message = String.Format("Count {0}", i);
                Console.WriteLine(message);
                await Task.Delay(1000);
            }

            Console.WriteLine("============End Task1============");
        }
    }

메인함수는 await 기준으로 비동기적으로 작업이 처리된다.

 

요약

async 메서드 내부에서 await을 만날게 되면 다음과 같은 경우의 수 가 있다.

1. awaitable이 예외를 발생시킨다면 await은 throw exception 한다.

2. awaitable이 이미 종료됐다면 메서드는 일반 메서드와 같이 동기적으로 실행된다.

3. awaitable이 종료된 상태가 아니라면 종료될 때 await 다음 코드가 실행되도록 대기 큐에 등록하고 async 메서드의 호출자에게 Task를 반환한다.

 

microsoft document 비동기 프로그래밍 예제

https://learn.microsoft.com/ko-kr/dotnet/csharp/programming-guide/concepts/async/#final-version

 

C#의 비동기 프로그래밍

async, await 및 Task를 사용하여 비동기 프로그래밍을 지원하는 C# 언어에 대해 간략히 설명합니다.

learn.microsoft.com

 

 

728x90
반응형

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

C# 키워드 : delegate, event, action  (0) 2023.01.31
C# 상수 키워드 : const  (0) 2023.01.31
C# 클래스 추상화 키워드 : abstract  (0) 2023.01.25
Main method  (0) 2023.01.19
테스트 환경  (0) 2023.01.17

abstract

추상적인

구현이 완전하지 않은 상태임을 타나내는 키워드이다.

클래스, 메서드, 프로퍼티, 인덱서, 이벤트와 함게 사용될 수 있다. 

일반적으로 추상 클래스를 구현하는데 사용되며 자체적으로는 인스턴스화 되지 않고 파생된 비추상 클래스에 의해 구현되어 사용된다. 

 

    abstract class Person
    {
        public abstract int GetInfo();
    }

    class Joon : Person
    {
        private int m_age;
        public Joon(int age) => m_age = age;
        public override int GetInfo() => m_age;
    }

    public class Program
    {
        static void Main(string[] args)
        {
            // Error, cannot create an instance of the abstract type.
            Person person = new Person(); 

            Joon joon = new Joon(30);
            Console.WriteLine(joon.GetInfo());
        }
    }

Feature

- 추상 클래스는 인스턴스화할수없다.

- 추상 클래스는 추상 메서드와 접근자를 포함할 수 있다.

- abstract 제한자는 sealed 제한자와 반대의미이므로 같이 사용할 수 없다.

  (abstract : 상속을 필요로하는 제한자, sealed : 상속을 방지하기위한 제한자)

- 추상 클래스로부터 파생된 클래스는 반드시 추상 메서드와 접근자의 구현이 필요하다.

 

메서드와 프로퍼티의 선언에서 abstract 제한자의 사용은 구현을 포함하지 않는것을 나타낸다.

- 추상 메서드는 암묵적으로 가상 메서드이다.

- 추상 메서드는 오직 추상 클래스 내에서만 선언이 허용된다.

- 추상 메서드는 구현이 없어야하므로 선언시 중괄호가 필요하지 않다.

 

Derived abstract class

추상 클래스를 파생 클래스로 만들어 특정 가상 메서드의 상속하여 추상 메서드로 가상 메서드를 재정의할 수 있다.

    public class BaseClass
    {
        public virtual void VirtualMethod(int i) { }
    }

    public abstract class AbstractClass : BaseClass
    {
        public abstract override void VirtualMethod(int i);
    }

	//DerivedClass.ViertualMethod는 BaseClass.VirtualMethod에 접근할 수 없다.
    public class DerivedClass : AbstractClass
    {
        public override void VirtualMethod(int i)
        {
            throw new NotImplementedException();
        }
    }

추상 클래스로부터 파생된 클래스는 메서드의 원래 구현에 접근할 수 없다. 

이러한 방식으로 추상 클래스는 파생 클래스로부터 가상 메서드의 구현을 강제할 수 있다.

728x90
반응형

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

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

메인 함수

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

 

.Net Framework

응용 프로그램을 구축하고 실행하기 위해 Microsoft에서 개발한 소프트웨어 개발 프레임워크 및 런타임 환경이다.

일반적인 C, C++ 같은 네이티브 언어로 만들어진 프로그램들이 운영체제에서 곧바로 실행되는 것과는 다르게 .Net 프레임워크를 기반으로 만들어진 응용 프로그램은 반드시 프레임워크가 설치된 환경이 요구된다.

 

.Net 프레임워크에서 사용되는 프로그래밍 언어는 대표적으로 C#과 Visual Basic이 있다.

해당 환경에서 개발된 프로그램은 컴파일 시 소스 코드를 IL(Intermediate Language)이라는 중간 언어로 바뀌는데 이때 IL코드는 메서드, 속성 및 기타 세부 정보를 포함한 메타 데이터와 함께 어셈블리라는 파일로 패키징 되어 저장된다. 어셈블리는 CLR에서 관리되며 런타임 실행 중에 JIT에 의해서 기계 언어로 변환된다. 이 기계언어 또한 지속해서 CLR에 의해서 유지 및 관리된다. 

 

이렇게 중간언어로 변경되는 과정이 있기 때문에 빌드환경과 실행환경이 다르더라도 실행환경에 맞춰서 런타임에서 기계언어를 맞춰서 만들어 내게 된다. 일반적인 네이티브 언어는 이러한 과정이 없기 때문에 환경이 바뀌면 문제가 생기는 경우가 발생하기도 한다.

 

IL

Intermediate Language

중간언어, 인간이 읽을 수 있는 소스코드가 컴파일러를 통해 해석될 때 완전한 네이티브 코드가 아닌 컴파일러나 소프트웨어 도구에 의해 추가 처리 또는 최적화될 수 있는 일련의 명령으로 변환되는데 이때 생성되는 파일에는 중간 언어라고 하는 명령어가 포함된다.

 

중간 언어는 쓰기 및 실행 사이의 가교 역할을 하는 언어로 컴파일러가 정밀한 최적화를 하도록 만들어 프로그램이 더 효율적으로 실행되도록 만들기도 하고 호환성이 없는 시스템 간에 이식 가능한 출력 파일을 생성하기 위해 사용되기도 한다.

언어의 실제 구문은 기계 코드 또는 인간이 읽을 수 없는 다른 유형의 바이트 코드와 유사하거나 또는 기존의 크로스 플랫폼 컴퓨터 프로그래밍 언어일 수도 있다.

.Net 프레임워크 환경은 다음과 같은 과정으로 작업이 진행된다.

.Net 호환 언어 > IL 코드 > CLR 실행 > CPU 기계어

IL 코드의 특이한 점은 ILASM.EXE라는 컴파일러를 가지고 있고 그 자체로 프로그래밍 언어의 문법을 가진다는 점이다.

 

CLR

Common Language Runtime 

.Net 프로그램 실행을 위한 런타임 환경을 제공한다. CLR은 구성요소들을 통해서 다양한 서비스를 제공하여 런타임에 프로그램의 전체 작업을 관리한다. 

 

JIT Compiler

Just In Time

중간 언어인 IL 코드를 하드웨어에서 실행할 수 있는 기계어로 변환한다. 

.Net 프로그램의 모든 어셈블리 및 코드를 기계어로 컴파일하지 않고 프로그램이 실행되는 런타임 동안 즉석에서 코드를 컴파일하여 필요한 코드만 컴파일한다. 실제로 실행에 필요한 코드를 컴파일할 수 있는 마지막 순간까지 기다리기 때문에 적시 컴파일 Junt In Time Compile이라고 한다. 이러한 작동 방식으로 다음과 같은 특징을 가진다.

 

메모리 사용량 감소

실제로 필요한 코드만 컴파일하기 때문에 사용되지 않는 코드는 컴파일되지 않으므로 메모리에 저장할 필요가 없어 프로그램에서 메모리 사용량을 절약할 수 있다.

 

향상된 성능

코드를 즉석에서 컴파일함으로 기본 하드웨어 및 시스템 구성에 대한 정보를 활용할 수 있기 때문에 최대 성능 및 효율성을 위해 코드를 최적화할 수 있다.

 

유연성

필요에 따라 코드를 컴파일할 수 있기 때문에 프로그램의 실행 흐름 또는 데이터 입력의  변경 사항에 적응할 수 있으므로 프로그램이 사용자 또는 시스템 입력에 더 유연하게 응답할 수 있다.

 

GC

Garbage Collection

더 이상 사용되지 않는 메모리를 식별하고 할당 해제하여 .Net 프로그램에서 사용하는 메모리를 자동으로 관리하는 프로세스이다.

 

Net 프로그램에서 개체는 프로그램 실행 중에 동적으로 생성되는데 이러한 개체를 저장하는 데 사용되는 메모리는 필요에 따라 할당 및 해제되어야 한다. GC는 프로그램에서 더 이상 참조하지 않는 개체를 식별하기 위해 메모리를 주기적으로 스캔하는 방식으로 작동한다. 그런 다음 해당되는 개체는 할당 해제되며 해당 메모리는 시스템에서 회수된다.

 

GC는 자동으로 사용되지 않는 메모리를 할당 해제하기 때문에 프로그램이 충돌하거나 예측할 수 없는 동작을 유발할 수 있는 메모리 누수를 방지하는데 도움이 된다. 또한 사용 가능한 메모리를 최적화하고 수동 메모리 관리의 오버헤드를 줄이면서 프로그램의 성능을 향상할 수 있으며 자동화된 프로세스를 통해 프로그래밍을 단순화할 수 있다.

 

하지만 GC는 사용되지 않는 개체를 식별하기 위해 주기적으로 메모리를 스캔하는 과정이 성능 오버헤드를 유발하기도 하며 메모리가 수거되는 동안 프로그램의 실행이 일시적으로 중지되거나 중단되는 등의 프로그램 응답성에 영향을 미칠 수 있다.

 

Exception Handling

프로그램 실행 중에 발생하는 오류 및 예외를 처리하기 위한 메커니즘을 제공하여 .Net 프로그램이 오류를 복구하고 계속 실행할 수 있도록 한다. 이 메커니즘은 개발자가 프로그램이 다양한 유형의 예외에 응답하는 방법을 지정할 수 있는 try/catch/finally 블록의 사용을 기반으로 한다. 

 

예외가 발생하면 CLR은 우선 예외 유형과 일치하는 catch 블록을 찾는다.

일치하는 catch 블록이 발견되면 해당 블록의 코드가 실행되어 프로그램이 적절한 방식으로 예외를 처리할 수 있다. 일반적으로 이 블록에서는 오류 메시지 로그나 대화 상자 표시 등을 처리한다.

 

일치하는 블록이 없으면 호출 스택에서 다음 상위 수준 catch 블록으로 예외가 전달되는데 어떤 수준에서도 블록이 발견되지 않으면 프로그램이 종료되고 오류 메시지가 표시된다.

 

예외를 효과적으로 처리할 수 있도록 제공되는 기능으로 Custom exception types, Exception filters, Stack traces 등이 있다.

 

Security Serviece

프로그램이 안전하게 실행되고 버퍼 오버플로 또는 인젝션 어택과 같은 공격에 취약하지 않도록 도움이 되는 다양한 보안 서비스를 제공한다.

 

CAS(Code Access Security)

코드 액세스 보안은 리소스 또는 중요한 데이터에 대한 무단 액세스를 방지하는 메커니즘으로 개발자가 다양한 코드 모듈이나 구성 요소에 대한 권한을 지정할 수 있으며 필요한 권한이 부여된 코드만 보호 중인 리소스에 액세스 할 수 있다.

 

Verification

CLR에는 프로그램 코드가 실행되기 전에 무결성과 안전성을 확인하는 확인 프로세스가 포함되어 있다. 확인 프로세스는 코드가 형식이 안전하고 버퍼 오버플로 또는 인젝션 어택과 같은 보안 취약성이 포함되어 있지 않은지 확인한다.

 

Sandboxing

프로그램을 서로 간에 그리고 기본 시스템으로부터 격리할 수 있는 샌드박싱 메커니즘을 제공한다. 샌드박싱은 프로그램에서 사용할 수 있는 권한과 리소스를 제한하고 악의적인 프로그램이 중요한 시스템 리소스나 데이터에 액세스 하지 못하도록 방지한다.

 

Secure execution

악성 코드가 시스템에서 실행되는 것을 방지하여 안전한 실행환경을 제공하여 프로그램이 안전하고 신뢰할 수 있는 환경에서만 실행되도록 악성 코드나 승인되지 않은 코드를 포함하지 않도록 한다.

 

Encryption

CLR은 중요한 데이터를 보호하고 무단 액세스를 방지할 수 있도록 데이터 암호화 및 암호 해복에 대한 지원을 한다. 이 암호화 메커니즘을 사용하면 디스크에 저장되거나 네트워크를 통해 전송되는 데이터를 보호할 수 있다.

 

Thread Management

개발자가 단일 프로그램 내에서 여러 스레드를 만들고 제어할 수 있도록 한다.

 

Thread Pool

개발자가 각 작업에 대해 새로운 스레드를 만드는 대신 여러 작업에 스레드를 재사용할 수 있도록 스레드 풀 메커니즘을 제공한다. 스레드 풀은 성능을 향상시키고 스레드 생성 및 소멸시 발생하는 오버헤드를 줄일 수 있다.

 

Thread Synchronization

여러 스레드가 공유 리소스나 데이터에 액세스할 때 발생할 수 있는 경합 상태 및 기타 동기화 문제를 방지하도록 다양한 동기화 메커니즘이 제공되는데 이 메커니즘에는 locks, mutexes, semaphores, synchronization primitives 가 있다.

 

Thread Prioritization

스레드의 우선 순위를 지정할 수 있어 중요한 작업이 먼저 실행되도록 할 수 있다. 우선 순위는 실행 예약 순서를 결정하는데 이것은 성능을 최적화하거나 중요한 작업이 먼저 실행되도록 하는 데 유용하다.

 

Thread Interruption

현재 실행 중인 스레드를 중단할 수 있는데 오래 실행되거나 응답하지 않는 스레드를 중지시킬 수 있다.

 

Thread Local Storage

여러 스레드 간에 공유되지 않고 특정 스레드에 로컬 데이터를 저장한다. 스레드 로컬 저장소는 성능을 최적화하거나 동기화 오버헤드를 줄일 수 있다.

 

Type System

.Net  호환 언어는 지켜야 할 타입의 표준 규격을 정의한 CTS를 만족한다면 누구나 새로운 언어를 만들어 .Net 프레임워크 상에서 실행할 수 있다. CTS의 모든 규격을 구현할 필요는 없으며 사용할 언어 사양에 맞게 구현하는 것도 가능하다.

CTS

Common Type System

공통 유형 시스템은 데이터 유형을 정의하고 사용하기 위한 표준이다.

데이터 유형은 언어 간 통합을 용이하게 하기 위해 런타임에 의해 사용되고 관리된다.

 

공용 언어 사양

CTS 이외에도 한 가지 지켜할 사항인 CLS가 있다.

직접 .Net  호환 언어를 만든다면 CTS는 전체를 구현할 필요가 없더라도 CLS만큼은 완벽하게 구현할 필요가 있는데 .Net 호환 언어끼리는 서로 사용할 수 있고 상속도 받을 수 있기 때문에 항상 외부에서 사용할 기능에 대한 호환성 문제를 염두하고 CLS를 준수해야 한다. 모든 .Net  호환 언어는 CLS에 정의한 사양만큼 구현하도록 하며 서로 간에 호출해야 하는 경우에는 그 기능에 한해서 만족시킬 수 있어야 한다.

 

CLS

Common Language Specification

완전한 상호운용성을 만들기 위한 언어의 공통점이다.

CTS의 서브셋으로 CLS의 규칙이 더 엄격하지 않은 이상 CTS 내의 모든 규칙이 CLS에 동일하게 적용될 수 있다.

 

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
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