언어/C# 46

C# 제너릭 - 3

검증 가능성과 제약조건 public static bool Min(T o1, T o2) { if (o1.CompareTo(o2) < 0) return o1; else return o2; } 위와같은 제너릭 메서드는 문제가 있다. T==0 으로 비교하는 과정에서 o1과 o2가 compareTo를 사용할 수 있는 타입인지 알 수 없기 때문이다. 따라서 CLR 은 제약조건이라는걸 제공해줘서 타입의 종류를 제한할 수 있게 해준다. public static T Min(T o1, T o2) where T : IComparable { if (o1.CompareTo(o2) < 0) return o1; else return o2; } 위처럼 where 토큰을 이용하여 T를 IComparable 인터페이스를 구현한 타입으로..

언어/C# 2021.01.20

C# - 제네릭 2

공변성과 반공변성 (델리게이트, 인터페이스) 델리게이트의 제네릭 타입 매개변수들에 공변성(Covariant)과 반공변성(Contra-Variant)의 성질을 나타낼 수 있다. 이런 기능일 이용하면 제네릭의 타입 인자가 달라도, 특정 제네릭 델리게이트 타입의 변수를 이와 호환되는 다른 델리게이트 타입으로 캐스팅할 수 있다. 제네릭 타입 매개변수는 다음 중 하나가 될 수 있다. 고정(Invariant) : 제네릭 타입 매개변수는 변경될 수 없음 반공변성 : 제네릭 타입 매개변수로 지정한 타입을 해당 타입을 상속한 (하위타입) 타입으로 변경할 수 있음. C#에서는 in 키워드를 사용. 입력 용도로 사용되는 인스턴스에 대해서만 적용 공변성 : 제네릭 타입 매개변수로 지정한 타입을 해당 타입이 상속한 (상위타입)..

언어/C# 2021.01.18

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