언어/C# 45

Task.Delay (vs Thread.Sleep)

개요 Task.Delay를 통해 진행중인 Task를 일시정지 할 수 있다. public static async Task DoSomethingAsync() { await Task.Delay(100); //100ms 이상 대기한다. return Thread.CurrentThread.ManagedThreadId; } 이를 이용하여 소프트 타임아웃을 구현할 수 있다. public static async Task TaskWithSoftTimeout() { Task someTask = DoSomethingAsync(); var timeoutTask = Task.Delay(100); //둘 중 하나가 완료되길 대기 var completeTask = Task.WhenAny(someTask, timeoutTask); i..

언어/C# 2024.04.10

동시성 개요

개념 정리 동시성 : 한 번에 두 가지 이상의 작업을 수행 멀티스레딩 : 다수의 실행 스레드를 사용하는 동시성의 한 형태 병렬 처리 : 많은 작업을 여러 스레드에 나눠 수행하는 멀티스레딩의 한 형태 비동기 프로그래밍 : 불필요한 스레드의 사용을 피하기 위해 퓨처나 콜백을 사용하는 동시성의 한 형태 리액티브 프로그래밍 : 앱이 이벤트에 대응하는 방식 병렬 프로그래밍 병렬 프로그래밍은 데이터 병렬과 작업 병렬로 나눌 수 있다. 데이터 병렬 : 처리해야 할 데이터들을 다른 데이터들과 독립적으로 처리할 수 있을 때 해당된다. 작업 병렬 : 작업 풀에 있는 작업들이 다른 작업과 독립적일 때 해당. 모든 작업이 독립적이면 동기화가 필요 없어지므로 병렬 처리가 극대화된다. 스레드 풀 스레드 풀은 알아서 작업을 잘 처..

언어/C# 2024.04.01

struct 와 in, readonly

struct의 복사 비용 struct는 단독으로 사용하면 힙에 생성되지 않는다는 장점이 있다. 그대신 다른 메서드의 매개변수 등으로 주어질 때 항상 값 복사가 일어난다. 당연히 struct 내부에 필드가 많으면 많을수록 복사 비용이 커지게 된다. public struct SomeStruct { public int A, B, C; } public static bool IsZero(SomeStruct s) { return (s.A | s.B | s.C) == 0; } 가령 IsZero메서드를 호출하면 SomeStruct의 복사가 일어난다. 이를 방지하고 싶으면 ref키워드를 쓸 수 있다.ref키워드로 값 타입을 넘길 땐, 해당 타입 전체를 스택에 복사하는 대신 해당 타입의 주소만을 복사한다. public s..

언어/C# 2024.03.20

가비지 없이 foreach 사용하기

문제foreach문은 syntax sugar이다. 내부적으로 해당 타입의 Enumerator를 받아 루프를 수행한다. public class SomeGenericClass : IEnumerable { public class SomeEnum : IEnumerator { public SomeEnum() { Console.WriteLine("Created"); } public bool MoveNext() { return false; } public void Reset() { throw new NotImplementedException(); } public T Current { get; } object IEnumerator.Current => Current; public void Dispose() { } } p..

언어/C# 2024.01.21

Dynamic 타입

Dynamic 리플렉션이나 다른 구성요소와 통신하는 일을 더 쉽게할 수 있도록 C# 컴파일러는 표현식의 타입을 dynamic으로 선언할 수 있게 했다. 만약 코드에서 dynamic으로 표시된 표현식이나 멤버를 호출하는 코드를 작성하면, 컴파일러는 페이로드(Payload)라 불리는 특별한 IL 코드를 생성한다. 실행 시점에서 페이로드 코드는 객체의 실제 타입을 기반으로 정확한 연산을 찾아 실행하는 일을 한다. public class Cat { public void Speak() { Console.WriteLine("Meow"); } } public class Dog { public void Speak() { Console.WriteLine("Woof"); } } public class Rock { } //..

언어/C# 2024.01.14

CLR? .NET? Mono?

선 정리 CTS, CLS는 닷넷 호환 언어가 지켜야하는 규약 닷넷 호환 언어는 CIL을 만들어낸다. CIL을 가지고 어떡할지에 대한 규격이 CLI CLI를 구현한 것이 CLR, Mono 닷넷 코어, 닷넷 프레임워크 등은 CLI 구현체 (ex. CLR)을 포함하고 추가적인 기능 제공 CIL CIL(Common Intermediate Language)는 그냥 IL이라고도 쓴다. IL코드는 CPU에 독립적인 결과물이다. 닷넷 호환 언어들은 소스코드를 IL로 컴파일하고, CLR같은 애들이 IL 코드를 CPU기계어로 최종 번역한다. . CTS CTS(Common Type System)는 닷넷 호환 언어가 뭘 구현할 수 있느냐를 정의한 규격. 가령 CTS에서는 다중 상속을 지원하지 않기 때문에 CTS를 만족하는 언..

언어/C# 2023.10.01

Blittable Types

Blittable Type이란 .NET Framework에서 사용하는 데이터 타입들로, 대충보면 int, float, double... 과 같은 애들이 포함되어 있음. 그러면 이걸 굳이 왜 정의해놓았느냐? 하면 Blittable Type들이 다른 애들보다 마샬링할 때 더 효율적이기 때문이다. 마샬링이란 어떤 오브젝트의 메모리 데이터를 전송/보관에 용이하도록 변환하는 행위를 의미한다. 당연히 서로 다른 프로그램 사이에 데이터를 교환하는 경우에도 마샬링이 사용됨. 서로 다른 프로그램이라면 데이터를 표현하는 방법도 다를 수 있는데, 이 때 managed memory와 unmanaged memory에서 동일한 데이터 표현방식을 갖는 애들이 Blittable Type임. 이런 BlittableType은 마샬링 할..

언어/C# 2023.05.13

beforefieldinit

개요 사실 읽을 필요 없다. 그런데 C# 싱글턴 초기화에 대한 유명한 아티클 을 보면 beforefieldinit이 뭔지 궁금해진다. 문제 class Test { static object o = new object(); } class Test { static object o; static Test() { o = new object(); } } class Test { static object o = new object(); static Test() { } } 위 세 코드는 모두 문법적으로 동일할까 아닐까? 정답은~~ 두구두구 아니다!! 두번째랑 세번째만 동일하고 첫번째는 아니다. 왜냐? 이유는 간단하다. 정적 생성자가 없는 첫번째는 BeforeFieldInit 플래그가 붙을 수도 아닐 수도 있다. 그런데 ..

언어/C# 2023.04.23

(C# 7.2) Span<T>

이게 뭐고 왜 쓰나 Provides a type-safe and memory-safe representation of a contiguous region of arbitrary memory. 마이크로소프트 Docs에서 정의하는 Span의 기능이다. 사실 저게 뭔 말인가 싶지만 '배열에 대한 참조 뷰(View)를 제공하는 타입' 이라고 생각하면 된다. 그렇다 DB에서 자주 쓰이는 그 view이다. 그렇다면 이걸 왜 쓰는가? 힙 메모리 할당을 줄이기 위해 사용한다. Span 는 readonly ref struct이다. ref struct는 오로지 스택에만 생성이 가능한 구조체이다. 사용 예 1. 배열에 대한 View를 제공 { var arr = new int[] { 0, 1, 2, 3 }; var left ..

언어/C# 2022.08.07

C# async/await

개념 async/await 메서드는 비동기 함수라고도 불린다. 기존에 존재하던 Task의 장점을 살려 개발자가 좀 더 쉽게 비동기 작업을 수행할 수 있는 프로그래밍 만들고자 하여 탄생한 것이 바로 async/await 되시겠다. await 연산자는 피연산자가 나타내는 비동기 작업이 완료될 때까지 수행을 중지한다. 그리고 await연산자를 포함한 메서드에 async를 붙여 컴파일러가 해당 함수가 비동기 함수임을 알 수 있게 한다. static async void SomeMethod() { await Task.Run(() => { SomeHeavyWork(); //시간이 좀 걸리는 메서드 }); //Task가 끝난 뒤에야 아래 코드가 시작된다. Console.WriteLine("SomeHeavyWork En..

언어/C# 2022.06.12