일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- gitlab
- 구조체
- 도커
- github
- Algorithm
- HTML
- Data Structure
- Unity
- Python
- c언어
- Flutter
- vim
- jupyter
- c# 추상 클래스
- 포인터
- c# winform
- C언어 포인터
- 깃
- 플러터
- docker
- c# 윈폼
- 다트 언어
- c#
- dart 언어
- C# delegate
- C++
- jupyter lab
- git
- 유니티
- Houdini
- Today
- Total
목록Programming (313)
nomad-programmer
COM 이란? COM은 Component Object Model의 약자로, 마이크로소프트의 소프트웨어 컴포넌트 규격을 말한다. OLE, ActiveX, COM+와 같은 파생 규격들이 모두 COM을 바탕으로 만들어졌다. 마이크로소프트에서 출시되는 대부분의 제품이 COM을 지원한다. COM은 부품 역할을 하는 소프트웨어이다. COM 컴포넌트는 그래픽 프로그래밍에 서툰 프로그래머가 화려한 차트 기능을 어플리케이션에 넣을 수 있도록 해주고, 엑셀 문서의 파일 구조를 몰라도 엑셀 문서를 읽거나 쓸 수 있도록 해준다. C#을 비롯한 .NET 언어들은 RCW(Runtime Callable Wrapper)를 통해 COM 컴포넌트를 사용할 수 있다. RCW는 .NET 프로엠워크가 제공하는 Type Library Impo..
dynamic 형식도 int, string과 같은 하나의 데이터 형식이다. 다만 형식 검사가 컴파일할 때 이루어지는 다른 형식과는 달리 형식 검사가 프로그램 실행 중에 이루어진다는 점이 다르다. class MyClass { public void FuncA() { } } class MainApp { static void Main(string[] args) { MyClass obj = new MyClass(); obj.FuncA(); // FuncB() 메소드는 정의되어 있지 않으므로 컴파일 에러 발생 obj.FuncB(); } } 위의 코드는 컴파일되지 않는다. MyClass 클래스는 FuncB() 라는 메소드가 선언되어 있지 않기 때문이다. class MyClass { public void FuncA()..
어트리뷰트(Attribute)는 코드에 대한 부가 정보를 기록하고 읽을 수 있는 기능이다. 어트리뷰트가 주석과 다른 점은 주석이 사람이 읽고 쓰는 정보라면, 어트리뷰트는 사람이 작성하고 컴퓨터가 읽는다는 것이다. 어트리뷰트를 이용해서 클래스나 구조체, 메소드, 프로퍼티 등에 데이터를 기록해두면 이 정보를 C# 컴파일러나 C#으로 작성된 프로그램이 이 정보를 읽어 사용할 수 있다. (예를 들어 컴파일러가 경고를 내도록 만들 수도 있음) 메타데이터 (Metadata) 메타데이터란 데이터의 데이터를 말한다. 가령 C# 코드도 데이터지만, 이 코드에 대한 정보, 데이터가 있을 수 있다. 이를 메타데이터라고 하는 것이다. 어트리뷰트나 리플렉션을 통해 얻는 정보들도 C# 코드의 메타데이터라고 할 수 있다. 어트리뷰..
리플렉션은 객체를 X-Ray 사진처럼 객체의 형식 정보를 들여다보는 기능이다. 이 기능을 이용하면 프로그램 실행 중에 객체의 형식 이름부터 프로퍼티 목록, 메소드 목록, 필드, 이벤트 목록까지 모두 열어볼 수 있다. 형식의 이름만 있다면 동적으로 인스턴스를 만들 수도 있고, 그 인스턴스의 메소드를 호출할 수도 있다. 심지어 새로운 데이터 형식을 동적으로 만들 수도 있다. 이렇듯 런타임에 형식 정보를 다룰 수 있게 하는 리플렉션은 한층 더 강력한 표현력을 선사한다. .NET은 모든 형식을 들여다 볼 수 있도록 장치를 설계했다. 바로 모든 데이터 형식의 조상인 Object 형식에 GetType() 메소드를 만들어 놓았다. Object.GetType() 메소드와 Type 클래스 Object는 모든 데이터 형식..
싱글턴(Singleton)이란? 해당 형식의 객체를 오직 단 하나만 마들고 이 객체를 전역에서 접근할 수 있도록 하는 디자인 기법이다. 기본값이 할당된 컬렉션은 참조용으로만 사용할 것이니 여러 개의 인스턴스가 필요 없다. 싱글턴을 이용하면 메모리 낭비를 줄일 수 있다. 표준 연산자 및 쿼리식 문법의 표 종류 메소드 이름 설명 C# 쿼리식 문법 정렬 OrderBy 오름차순으로 값을 정렬 orderby OrderByDescending 내림차순으로 값을 정렬 orderby ... descending ThenBy 오름차순으로 2차 정렬 orderby ..., ... ThenByDescending 내림차순으로 2차 정렬 orderby ..., ... descending Reverse 컬렉션 요소의 순서를 거꾸로 ..
LINQ는 매우 깔끔하고 쉽게 읽고 쓸 수 있지만, 일반적으로 알고리즘을 수동으로 작성하는 것보다 훨씬 더 많은 계산, 특히 더 많은 메모리 할당이 필요하다. 이 점을 반드시 알고 있어야 한다. using System.Linq; List data = new List(); data.Any(x => x > 10); var result = from x in data where x > 10 select x; 그렇기때문에 Unity에서는 LINQ를 사용하지 않도록해야한다. https://docs.microsoft.com/ko-kr/dotnet/csharp/language-reference/keywords/let-clause let 절 - C# 참조 let 절 - C# 참조 docs.microsoft.com LIN..
메소드를 비롯하여 속성, 인덱서, 생성자, 소멸자는 공통된 특징이 있다. 이들은 모두 클래스의 멤버로서 본문이 중괄호{}로 만들어져 있다. 이러한 멤버의 본문을 식(expression)만으로 구현하는 것이 가능하다. 이렇게 구현된 멤버를 영어로 "Expression-Bodied Memeber" 라고 하고, "식 본문 멤버" 라고 한다. 문법은 다음과 같다. 멤버 => 식; 아래는 읽기 전용 속성과 인덱서를 식으로 구현하는 방법이다. 읽기 전용으로만 사용한다고 가정하면 get 키워드조차 생략할 수 있다. class Foo { public int Capacity => list.Capacity; public string this[int index] => list[index]; } 허나 읽기/쓰기 모두 가능한 ..
자료 구조에서 말하는 이진 트리 자료 구조라고 생각하면 된다. 각 노드는 부모-자식 관계로 연결된다. 뿌리가 되는 노드를 루트(Root) 노드라고 하며 루트로부터 뻗어 나온 노드 중 가장 끝에 있는 노드를 잎(Leaf) 노드, 또는 단말(Terminal) 노드라고 한다. 평범한 트리 자료 구조에서는 부모 노드가 여러 개의 자식 노드를 가질 수도 있지만, 식 트리는 한 부모 노드가 단 두 개만의 자식 노드를 가질 수 있는 "이진 트리(Binary Tree)"이다. 식 트리(Expression Tree)란, 식을 트리로 표현한 자료 구조를 말한다. 예를 들어 1 * 2 + (7 - 8) 이라는 식을 식 트리로 표현하면 다음과 같다. 식 트리에서 연산자는 부모 노드가 되며, 피연산자는 자식 노드가 된다. 위의..
Func와 Action을 사용하는 이유? Func와 Action으로 더 간편한 무명 함수를 만들 수 있다. 익명 메소드와 무명 함수는 코드를 보다 간결하게 만들어주는 요소들이다. 하지만 대부분의 경우 단 하나의 익명 메소드나 무명 함수를 만들기 위해 매번 별개의 대리자를 선언해야 한다. 번거로운 일이 아닐 수 없다. 이 문제를 해결하기 위해 MS는 .NET 프레임워크에 Func와 Action 대리자를 미리 선언해뒀다. Func 대리자는 결과를 반환하는 메소드를 참조한다. Action 대리자는 결과를 반환하지 않는 메소드를 참조한다. Func 대리자 Func 대리자는 결과를 반환하는 메소드를 참조하기 위해 만들어졌다. .NET 프레임워크에는 모두 17가지 버전의 Func 대리자가 준비되어있다. public..
람다식(Lambda Expression) 은 무명 함수(Anonymous Function) 라는 이름으로 부른다. // 기본적인 람다식 선언 매개변수목록 => 식 "=>" 연산자는 "입력" 연산자이다. 이 연산자가 하는 역할은 그저 매개 변수를 전달하는 것뿐이다. 람다식에서는 => 를 중심으로 왼쪽에는 매개 변수가 오른편에는 식이 위치한다. // 익명 메소드를 위한 대리자 선언 delegate int Calculate(int a, int b); // ... static void Main(string[] args){ Calulate calc = (int a, int b) => a + b; } C# 컴파일러는 람다를 한층 더 간결하게 만들 수 있도록 "형식 유추(Type Inference)" 라는 기능을 제..
알람 시계처럼 어떤 일이 생겼을 때 이를 알려주는 객체가 필요한 경우가 있다. 이런 객체를 만들 때 사용하는 것이 바로 "이벤트 (Event)" 이다. 이벤트의 동작 원리는 대리자와 거의 흡사하다. 이유는 이벤트는 대리자를 event 한정자로 수식해서 만들기 때문이다. 이벤트 선언 및 사용 절차 대리자 선언. 대리자는 클래스 밖에 선언해도 되고 안에 선언해도 된다. 클래스 내에 1에서 선언한 대리자의 인스턴스를 event 한정자로 수식하여 선언. 이벤트 핸들러를 작성. 이벤트 핸들러는 1에서 선언한 대리자와 일치하는 메소드면 된다. 클래스의 인스턴스를 생성하고 이 객체의 이벤트에 3에서 작성한 이벤트 핸들러를 등록한다. 이벤트가 발생하면 이벤트 핸들러가 호출된다. 이벤트 예제 using System; n..
익명 메소드란 이름이 없는 메소드를 말한다. 익명 메소드는 delegate 키워드를 이용하여 선언한다. 대리자 인스턴스 = delegate(매개변수 목록) { // 실행하고자 하는 코드 }; 익명 메소드는 자신을 참조할 대리자의 형식과 동일한 형식으로 선언되어야 한다. delegate int Calculate(int a, int b); public static void Main(){ Calculate calc; calc = delegate(int a, int b){ return a + b; }; } 반환 형식을 int로 선언했다면 익명 메소드도 int 형식의 결과를 반환해야 하며, 대리자에서 int 형식의 매개 변수 2개를 받도록 선언했다면 익명 메소드도 역시 동일하게 매개 변수를 받도록 구현해야 한다...
대리자에는 유용한 속성이 있다. 그것은 바로 대리자 하나가 여러 개의 메소드를 동시에 참조할 수 있다는 것이다. delegate void MyDelegate(string message); void Msg1(string msg){ Console.WriteLine("Msg1() : {0}", msg); } void Msg2(string msg){ Console.WriteLine("Msg2() : {0}", msg); } void Msg3(string msg){ Console.WriteLine("Msg3() : {0}", msg); } MyDelegate foo = new MyDelegate(Msg1); foo += new MyDelegate(Msg2); foo += new MyDelegate(Msg3); f..
대리자는 보통의 메소드뿐 아니라 일반화 메소드도 참조할 수 있다. 물론 이 경우에는 대리자도 일반화 메소드를 참조할 수 있도록 형식 매개 변수를 이용하여 선언되어야 한다. 형식 매개 변수를 이용해서 대리자를 선언하는 요령은 메소드와 같다. 괄호 사이에 형식 매개 변수를 넣어주면 된다. 일반화 대리자 예제 using System; namespace test { delegate int Compare(T a, T b); internal class Program { static int AscendCompare(T a, T b) where T: IComparable { return a.CompareTo(b); } static int DescendCompare(T a, T b) where T : IComparabl..
대리자와 이벤트 사건을 영어로는 이벤트(Event)라고 하는데, 컴퓨터에 발생하는 이벤트에 반응하도록 프로그램을 만드는 것을 일컬어 "이벤트 기반 프로그래밍(Event Driven Programming)" 이라고 부른다. 멀티 패러다임 언어인 C#이 지원하는 또 하나의 프로그래밍 패러다임인 셈이다. 이벤트 기반 프로그래밍은 GUI(Graphic User Interface) 를 만들 때 특히 유용하다. C#에서 지원하는 이벤트 기반 프로그래밍을 이해하려면 먼저 대리자를 알아야 하고 그 다음 이벤트를 알아야 한다. 2020/06/16 - [Programming/C] - [C] 함수 포인터 2020/06/16 - [Programming/C] - [C] 콜백 함수 2020/06/18 - [Programming/..
예외는 throw 문을 이용하여 던진다. 그래서 던진 예외를 try~catch로 받는다. throw 는 보통 문(statement)으로 사용하지만 C#7.0부터는 식(expression)으로도 사용할 수 있도록 개선되었다. int? foo = null; // foo는 null이므로 bar에 foo를 할당하지 않고 throw 식이 실행된다. int bar = foo ?? throw new ArgumentNullException(); // 조건 연산자 안에서도 사용할 수 있다. int[] array = new int[] {1, 2, 3}; int index = 4; // 삼항 연산자를 이용한 예외 던지기 int value = array[ index >= 0 && index < 3 ? index : throw..
foreach를 사용할 수 있는 클래스를 만드려면 IEnumerable 인터페이스와 IEnumerator 인터페이스를 상속하고 이들에게 선언되어 있는 메소드와 프로퍼티를 구현해야 한다. 일반화 클래스도 IEnumerable과 IEnumerator 인터페이스를 상속하여 이들의 메소드와 프로퍼티를 구현하면 일반은 foreach를 통해 순회를 할 수 있지만, 요소를 순회할 때마다 형식 변환을 수행하는 오버로드가 발생한다는 문제가 있다. 성능을 위하여 기껏 일반화를 통해 형식 변환을 제거하였더니 foreach 구문에서 형식 변환을 일으켜 성능을 저하시키면 너무 바보 같은 일일것이다. System.Collections.Generic 네임스페이스에는 이 문제를 풀 수 있는 열쇠를 가지고 있다. 바로 IEnumera..
System.Collections 의 컬렉션들은 어떤 형식이든 object 형식으로 상속받고 있으므로 object 형식으로 형식 변환이 가능하다. 이것은 바로 이점을 활용하기 위해 만들어진 자료 구조이다. 컬렉션 객체에 int 형 데이터, string 형 데이터, FooClass 의 객체도 담을 수 있다. 하지만 컬렉션은 object 형식에 기반하고 있기 때문에 태생적으로 성능 문제를 안고 있다. 컬렉션의 요소에 접근할 때마다 형식 변환이 주구장창 일어나기 때문이다. "일반화 컬렉션 (System.Collections.Generic)" 은 object 형식 기반의 컬렉션이 갖고 있던 문제를 말끔히 해결한다. 일반화 컬렉션은 말 그대로 일반화에 기반해서 만들어져 있기 때문에 컴파일할 때 컬렉션에서 사용할 ..
일반화 메소드나 일반화 클래스가 입력받는 형식 매개 변수 T는 "모든" 데이터 형식을 대신할 수 있다. 이렇게 모든 형식에 대응할 수 있는 형식 매개 변수가 필요한 때도 있지만, 종종 특정 조건을 갖춘 형식에만 대응하는 형식 매개 변수가 필요할 때도 있다. 이 때 형식 매개 변수의 조건에 제약을 줄 수 있다. 예를 들어 MyList 클래스의 형식 매개 변수 T에 "MyClass 로부터 상속받는 형식이어야 할 것" 이라는 제약을 주면 다음과 같이 클래스 선언문의 헤더에 where 절을 추가해주면 된다. class MyList where T : MyClass { // ... } 일반화 메소드도 비슷하다. CopyArray() 의 형식 매개 변수 T에 "값 형식이어야 할 것" 이라는 제약은 다음과 같이 줄 수..
C++ 언어에서의 "템플릿 (Template)" 이라고 생각하면 된다. template C#은 프로그래머가 작성한 하나의 코드가 여러 가지 데이터 형식에 맞춰 동작할 수 있도록 "일반환 프로그래밍" 을 지원한다. 일반환 프로그래밍은 코드 생산성을 좌우하는 아주 중요한 요소이며 일반화 컬렉션은 반드시 익혀둘 필요가 충분하다. 특수한 개념으로부터 공통된 개념을 찾아 묶는 것을 "일반화 (Generalization)" 라고 한다. "일반화 프로그래밍 (Generic Programming) " 은 이러한 일반화를 이용하는 프로그래밍 기법이다. 일반화하는 대상은 "데이터 형식 (Data Type)" 이다. void CopyArray( int[] source, int[] target) { for(int i=0; i..