목록C# (122)
방프리
Item 23 : 타입 매개변수에 대해 메서드 제약 조건을 설정하려면 델리게이트를 활용하라. 특정 행위를 하는 클래스를 생성할 때 메서드를 이용하기보다는 델리게이트로 구현하는 방법이 더 효율적인 경우가 있다. 예로 캐릭터들의 이동이라는 함수를 만들 때 모든 캐릭터들은 이동을 하기 때문에 IMove라는 인터페이스를 만든 후 구현하는 것이 보편적이다. 하지만 Move()라는 메서드를 호출하기 위해 IMove 인터페이스를 만들고 그것을 상속하고... 작업량이 굉장히 많아진다. 하지만 이 메서드를 생성하는 방식 대신에 델리게이트를 이용한다면 굳이 인터페이스를 생성하지 않고 불필요한 작업량을 줄일 수 있다 (= 코드 양을 줄일 수 있다.) public static class ReplaceInterface { pu..
Item 22 : 공변성과 반공변성을 지원하라 공변성과 반공변성은 무엇일까? 단어부터 생소하다. 타입의 가변성으로도 말하는데 특정 타입의 객체를 다른 타입의 객체로 변환할 수 있는 성격을 말한다. abctract public class CelestialBody : IComparable { public double Mass { get; set; } public string Name { get; set; } } public class Planet : CelestialBody { } public class Moon : CelestialBody { } public class Asteroid : CelestialBody { } [예제에 사용될 클래스들] 공변성 X를 Y로 바꾸어 사용할 수 있는 경우, C를 C로도..

Item 21 : 타입 매개변수가 IDisposable을 구현한 경우를 대비하여 제네릭 클래스를 작성하라 제약조건은 두 가지 역할을 한다. (1) 런타임 오류가 발생할 가능성이 있는 부분을 컴파일 타임 오류로 대체 (2) 타입 매개변수로 사용할 수 있는 타입을 명확히 규정하여 사용자에게 도움 하지만 타입 매개변수로 지정된 타입이 제약 조건을 통해 요구하는 작업 외에 다른 작업을 추가로 수행할 수 있는지에 대해서는 신경쓰지 않는다. 하단의 코드는 제네릭 메서드 내에서 타입 매개변수로 주어지는 타입을 이용해 인스턴스를 생성할 때의 처리다. using 구문을 통해 해당 타입에 IDisposable이 구현되어 있는지 확인 후 해당 함수를 실행시키는 것이다. (쉽게 생각해서 null 체크를 한 것이다.) 함수가 ..

Item 20: IComparable와 IComparer를 이용하여 객체의 선후 관계를 정의하라 앞에서의 Enumerable과 같이 인터페이스를 통해 Compare를 구현할 수 있다. 이 IComparable는 CompareTo()라는 메서드 하나만을 정의하고 있는데 이 함수는 C 라이브러리의 strcmp 함수의 구현방식을 그대로 따르고 있다. .NET 환경에서 최신 API들은 IComparable를 사용하지만, .Net Framework 2.0이하에서는 object 타입을 받는 IComparable을 사용하고 있기 때문에 두 가지를 같이 구현해주어야 한다. 하지만 위의 코드는 object 타입을 받기 때문에 연산량이 굉장히 많아진다. (박싱과 언박싱) 위의 코드에서는 선후 관계를 명시된 타입으로 재정의..

Item 19 : 런타임에 타입을 확인하여 최적의 알고리즘을 사용하라 제네릭 타입을 사용할 때 알고리즘이 특정 타입에 대해 더 효율적으로 동작한다고 생각되면 그 타빙르 이용하도록 코드를 작성해야한다. 제약 조건을 설정하는 것은 항상 효과적인 방법이 아니기 때문이다. 제네릭의 인스턴스화는 런타임의 타입을 고려하지 않으며 컴파일타임의 타입만을 고려한다.

Item 18: 반드시 필요한 제약 조건만 설정하라 이 주제에 앞서 제약 조건이란? 클래스가 작업을 올바르게 수행하기 위해서 타입 매개변수로 전달할 수 있는 타입의 유형을 제한하는 방법이다. 제약 조건을 적절히 잘 사용하면 예외에 대한 처리를 쉽게 할 수 있으나 너무 설정하지 않으면 런타임에 들어가는 예외처리가 많아지고 그렇다고 너무 조건이 있으면 해당 클래스를 사용 하기 위해 추가작업이 많이 들어가게 된다. 이 제약 조건은 제네릭 타입에 대해 우리가 가정하고 있는 사실을 컴파일러와 다른 개발자에게 알려주는 용도로 사용된다. 컴파일러에게 제약 조건을 알려주는 것은 컴파일러 입장에서 두 가지 장점이 있는데 첫 번째는 제네릭 타입을 작성할 때, 두 번째는 제네릭 타입을 사용하는 하용자가 타입 매개변수로 올바..

Item 17: 표준 Dispose 패턴을 구현하라 C++에서 코딩할 때 가장 중요한 것은 메모리 관리이다. 솔직히 DirectX나 학교 과제로 MFC 공부할 때, 특히 서버 개발 일을 할 때 메모리 관리하는 것은 굉장히 신경쓰이고 짜증나는 일이었다. C#에서는 가비지 컬렉터가 알아서 처리해주니까 이에 대한 부담감이 확실히 덜하긴 하지만 내부적으로 봤을 때 가비지 컬렉터도 코드로 돌아가고 있는 존재이기 때문에 마냥 안심만은 할 수가 없다. 또한 메모리라는 것이 가비지컬렉터가 알아서 해주면 편하지만 이 시점을 개발자들이 제대로 알 수 없기 때문에 버그를 만들 수도 있다. 예로 언리얼 엔진 서밋에 참가했을 때 맨 처음 C#으로 개발을 진행했던 프로젝트가 메모리가 해제되는 시점을 제대로 알 수 없어서 C++로..

Item 16: 생성자 내에서는 절대로 가상 함수를 호출하지 말라 C++과 C#에서 생성자가 동작하는 방식의 기준은 많이 다르다고 한다. 그로 인해 개발자들이 예상하는 값과는 전혀 다른 형태의 값을 출력할 때도 있다. 다음의 코드를 분석하면 C++ 개발자들은 보통 "VFunc in B" 이 출력될 것이라 생각하지만 C#은 생성자 구문에 인스턴스가 들어오면 초기화가 끝났다고 판명하기 때문에 선언과 동시에 초기화를 해준 "Set by initializer"가 마지막으로 출력이 된다. C++은 가상함수가 생성 중인 객체의 타입을 확인하도록 되어있으나, C#은 다르다. 또한 C#은 현재 타입이 추상 베이스 클래스인 경우 가상 메서드가 null 메서드 포인터가 될 가능성을 배제하였다. C#의 컴파일러는 런타입 때..