분류 전체보기 188

C# 제너릭 - 1

일반 제너릭 타입이나 메서드를 정의할 때 ,를 붙여 데이터 타입을 지정하지 않고도 동작할 수 있음을 나타내는데 이 때 T와 같이 데이터 타입으로 지정하는 변수를 타입 매개변수라고 한다. 또한 제네릭 타입이나 메서드를 사용할 때, 지정하는 데이터 타입을 타입 인자라고 한다. 마이크로소프트의 디자인 가이드라인에 따르면 제네릭 매개변수는 첫 글자를 대문자로 시작하고 접두사로 T를 붙인다. (TValue, TKey...) 제네릭이 개발자들에게 제공하는 이점은 다음과 같다. 소스 코드 보호 : 제네릭 알고리즘을 사용하기 위해 알고리즘을 구현하는 소스 코드가 반드시 필요하지는 않다. (먼소리지) 타입 안정성 : 지정된 타입과 호환하는 타입에 대해서만 사용할 수 있도록 한다. 그렇지 않으면 컴파일 에러가 발생한다. ..

언어/C# 2021.01.09

C# 이벤트

이벤트 설계 1. 이벤트 리스너들에게 보내는 정보 타입을 정의하기 보통 리스너들에게 보낼 정보들은 단일 클래스로 캡슐화 되며 private 필드와 이 필드들에 대한 읽기 전용 속성들을 포함한다. 편의상 이런 정보를 전달용 클래스는 System.EventArgs 타입을 상속한 타입으로 정의하는게 일반적이다. 또 이름에도 EventArgs라는 접미사를 관습적으로 붙인다. // 정보 전달용 클래스 public sealed class NewMailEventArgs : EventArgs { private readonly string m_from, m_to; public NewMailEventArgs(string from, string to) { m_from = from; m_to = to; } public str..

언어/C# 2021.01.02

C# 속성 (Property) - 2

익명 타입 var anon = new { Name = "Yang", Year = 1993 }; Console.WriteLine($"Name : {anon.Name}, Year = {anon.Year}"); 위와 같은 방법으로 익명 타입을 생성할 수 있다. 저렇게 익명 타입을 생성하면 컴파일러가 알아서 이름을 붙여주며, var을 이용해서 타입을 유추할 수 있게 된다. 컴파일러가 하는 일을 더 자세히 보면, 각각의 표현식으로 부터 정확한 타입을 유추하여 private readonly 필드를 만들고, 각각의 속성을 정의하며 주어진 값들을 받을 수 있는 생성자를 정의한다. 추가적으로 Equals, GetHashCode, ToString 메서드까지 제정의한다. 다음과 같이 이름을 유추하거나, 배열로도 사용할 수 ..

언어/C# 2020.12.27

C# 속성 (Property) - 1. 속성, 매개변수 없는 속성

속성 (property) 속성은 메서드를 소스 코드상에서 호출하는 방법을 단순하게 만들어준다. CLR은 흔히 속성이라고 이야기하는 매개변수 없는 속성과 매개변수가 있는 속성 (C#에서는 인덱서)를 지원한다. 매개변수 없는 속성 객체지향에서 중요한건 데이터 캡슐화이다. 클래스에서 정의한 필드가 외부에 노출되지 않도록 하여 필드의 상태 보호하는 것이다. 예를 들어, Person p = new Person(); p.Age = -1; //나이가 음수? 위와 같은 코드는 쉽게 필드의 상태를 훼손시킨다. 뿐만 아니라, 값을 캐쉬에 보관하거나, 내부 객체를 지연생성 하거나 쓰레드 안정적으로 접근해야 하는 경우에도 데이터 캡슐화를 하는게 중요할 수 있다. 따라서 타입을 설계할 때는 모든 필드를 가능한 private으로..

언어/C# 2020.12.20

C# 매개변수

선택된 매개변수와 명명된 매개변수 메서드의 매개변수를 정할 때 일부 또는 전체에 대해 기본값을 정할 수 있다. public static void M(int a = 1, int b = 2, int c = 3) { } public static void Main() { M(); //M(1,2,3) M(1, c: 2, b: 1); // 콜론(:) 을 이용해서 값을 전할 매개변수를 고를 수 있다. } 호출 시점에 매개변수를 생략하면 ,C# 컴파일러는 매개변수의 기본값을 포함하는 코드를 생성한다. 모듈 외부에서 불리는 메서드의 경우 기본값을 바꾸는건 위험할 수 있는데, 만약 매개변수의 기본값을 바꾼 경우 호출하는 쪽의 코드도 다시 컴파일 하지 않으면 예전의 기본값을 가진 메서드를 호출하기 때문이다. 따라서 publ..

언어/C# 2020.12.13

C# - @ (verbatim identifier)

verbatim : 말 그대로 라는 뜻 다 필요 없고 다음 소스코드들 보면 끗 // 예약어를 변수 이름으로 쓸 수 있게 해준다. string[] @for = { "Hello", "World" }; for (int i = 0; i < @for.Length; i++) { Console.WriteLine(@for[i]); } //문자열을 '말 그대로' 쓴다. string filename1 = @"c:\work\trunk\something.txt"; string filename2 = "c:\\work\\trunk\\something.txt"; Console.WriteLine(filename1); Console.WriteLine(filename2); // 둘다 c:\work\trunk\something.txt 를..

언어/C# 2020.12.07

C# 메서드 - 3. 확장 메서드

확장 메서드 확장 메서드는 프로그래머가 정의한 정적 메서드를 인스턴스 메서드의 일부인 것처럼 사용할 수 있게 하는 기능이다. 예를 들어 C# 제너릭의 List 에는 요소들을 섞어주는 Suffle() 메서드가 존재하지 않는다. 이 경우 List를 매개변수로 받아 요소들을 섞어주는 메서드를 만들 수 있지만 그것보다는 List에서 직접 호출하는 편이 더 보기 좋을 것이다. 이 경우 다음과 같이 확장 메서드를 정의하면 된다. using MyExtentions; namespace MyExtentions { public static class MyListExtensions { public static void Suffle(this List list) { // 대충 섞는 과정 } } } public sealed cl..

언어/C# 2020.11.28

C# 메서드 - 2. 연산자 오버로드 메서드

연산자 오버로드 메서드 CLR 사양에 따르면 연산자 오버로드 메서드는 반드시 public이면서 static이어야 한다. 또한 C#을 포함한 많은 언어들이 연산자 메서드의 매개변수는 반드시 연산자 메서드가 정의된 타입과 같은 타입이어야 한다는 조건도 포함되어있다. 이렇게 하는 이유는 컴파일러가 적절한 시간 내에 가능한 연산자 메서드를 찾아 쉽게 연결할 수 있도록 하기 위함이다. 연산자 오버로드는 다음과 같이 사용할 수 있다. public sealed class MyClass { public static MyClass operator - (MyClass a, MyClass b) { return new MyClass(); } // 이항 연산자 - public static MyClass operator - (M..

언어/C# 2020.11.28

C# 메서드 - 1. 생성자

인스턴스 생성자 - 클래스 (참조타입) 생성자는 항상 .ctor이라는 이름으로 불리고 이 이름으로 메서드 정의 메타데이터 테이블에 등록된다. 참조 타입으로 객체의 인스턴스를 생성하면, 데이터 필드들을 저장하기 위한 메모리가 할당되는데 그 과정에서 먼저 객체의 오버헤드 필드(타입 객체 포인터와 동기화 블록 인덱스)가 초기화되고, 그 다음에 타입의 인스턴스 생성자가 호출되어 객체의 초기 상태를 설정한다. 참조타입의 객체를 생성하면, 할당된 메모리는 우선 모두 0으로 초기화되며, 이후 타입의 인스턴스 생성자가 호출된다. 다른 메서드들과 다르게 인스턴스 생성자는 상속되지 않는다. (따라서 virtual,new,override,sealed,abstract 같은 키워드를 사용할 수 없다.) 만약 클래스를 정의할 때..

언어/C# 2020.11.22

C# 의 타입 - 4. 객체의 식별 (Equals, GetHashCode)

Equals System.Object 타입은 Equals 가상 메서드를 제공한다. 매개변수로 지정한 객체가 현재 객체와 동일하다고 판단하면 true를 반환한다. 다음과 같은 Equals 메서드가 있다고 하자 public virtual bool Equals(Object obj) { if(this == obj) return true; return false; } 두 객체의 포인터 주소가 동일하다면 같은 객체를 가리키는 것이므로 참을 반환하는 것은 옳다. 그러나 이것은 객체들의 값들을 비교하지는 못하므로 때에 따라서 적절하지 못할 수 있다. 그래서 프로그래머는 때때로 Equals를 재정의해서 사용해야 하는데, 이 때 객체가 같은 값을 가리키는지 확인하는 게 불가능해지므로 Object타입 내에서 Referenc..

언어/C# 2020.11.14