반응형

개발공부/C# 34

[Effective C#] 아이템 24 : 베이스 클래스나 인터페이스에 대해서 제네릭을 특화하지 말라

컴파일러는 제네릭 메서드의 타입 매개변수가 다른 타입으로 다양하게 변경될 수 있음을 고려하여 오버로드된 메서드 중 하나를 선택한다. 그런데 이런 동작 방식을 제대로 인지하지 못하면, 프로그램이 이상하게 동작할 수 있다. namespace _210210_Item24Ex { public class MyBase { } public interface IMessageWriter { void WriteMessage(); } public class MyDerived : MyBase, IMessageWriter { void IMessageWriter.WriteMessage() => WriteLine("Inside MyDerived.WriteMessage"); } public class AnotherType : IMes..

개발공부/C# 2021.11.30

[Effective C#] 아이템 23 : 타입 매개변수에 대해 메서드 제약 조건을 설정하려면 델리게이트를 활용하라

인터페이스를 이용한 메서드 제약 제네릭 클래스에 대해 타입 매개변수 T가 반드시 Add() 메서드를 가져야 한다는 제약 조건을 설정할 때, Add() 메서드를 정의하는 IAdd 인터페이스를 생성한다. IAdd 인터페이스로 제약 조건을 설정한다. IAdd를 구현할 클래스를 생성한다. IAdd가 정의한 Add() 메서드를 구현한다. 제네릭 클래스의 정의를 이용하여 닫힌 제네릭 클래스를 만든다. 즉, Add() 메서드 하나를 호출하기 위해 IAdd 인터페이스를 구현한 새로운 클래스를 생성한다. 델리게이크를 이용한 메서드 제약 제약조건으로 설정하고 싶은 메서드의 원형에 부합하는 델리게이트를 작성한다. 적절한 메서드의 원형을 고안하고 이를 델리게이트 타입으로 정의한다. 델리게이트의 인스턴스를 제네릭 메서드의 매개..

개발공부/C# 2021.11.29

[Effective C#] 아이템 22 : 공변성과 반공변성을 지원하라

공변과 반공변 특정 타입의 객체를 다른 타입의 객체로 변환할 수 있는 성격. 공변 : X를 Y로 바꿔 사용할 수 있는 경우, C를 C로 바꾸는 것이 가능하면 C는 공변이다. 반공변 : Y를 X로 바꿔 사용할 수 있는 경우, C를 C로 바꾸는 것이 가능하면 C는 반공변이다. 공변성과 반공변성은 가변성(variance)라고 부른다. ↔ 불변성(invariant) 변환 지원 방법 제네릭 인터페이스나 델리게이트의 정의 부분에 데코레이터를 추가해야 한다. 데코레이터 : 제네릭 공변/반공변을 지원한다는 의미 제네릭 타입에 대한 공변 공변과 반공변을 지원하는 in, out 키워드. 이 데코레이터는 주로 제네릭 인터페이스나 델리게이트 선언 시에 사용할 수 있다. public static void CovariantGen..

개발공부/C# 2021.11.28

[Effective C#] 아이템 21 : 타입 매개변수가 IDisposable을 구현한 경우를 대비하여 제네릭 클래스를 작성하라

제약 조건의 역할 런타임 오류가 발생할 가능성이 있는 부분을 컴파일 타임 오류로 대체한다. 타입 매개변수로 사용할 수 있는 타입을 명확히 규정하여 사용자에게 도움을 준다. 제약조건은 타입 매개변수가 무엇을 해서는 안되는지를 정의할 수 없다. 이때, 타입 매개변수로 지정하는 타입이 IDisposable을 구현하고 있다면 추가 작업이 필요하다. 제네릭 메서드 내에서 타입 매개변수로 주어지는 타입을 이용하여 인스턴스를 생성할 경우 public interface IEngine { void DoWork(); } public class EngineDriverOne where T : IEngine, new() { public void GetThingsDone() { T driver = new T(); using (d..

개발공부/C# 2021.11.27

[Effective C#] 아이템 20 : IComparable<T>와 IComparer<T>를 이용하여 객체의 선후 관계를 정의하라

IComparable와 IComparer 객체의 선후 관계를 정의하기 위한 인터페이스 IComparable : 타입의 기본적인 선후 관계를 정의한다. IComparable를 사용할 때는 IComparable도 함께 구현해야 한다. IComparer : 기본적인 선후 관계 이외에 추가적인 선후 관계를 정의한다. 타입 내 관계 연산자를 재정의하면 해당 타입에 최적화된 방식으로 객체의 선후 관계를 판단할 수 있다. (효율성 증가) CompareTo() 메서드란? 현재 객체가 대상 객체보다 작으면 0보다 작은 값을, 같으면 0을, 크면 0을 리턴하는 함수. IComparable 인터페이스에 유일하게 정의되어있다. IComparable 타입의 참조를 통해서만 호출된다. IComparable의 단점 인터페이스를 구..

개발공부/C# 2021.11.26

[Effective C#] 아이템 19 : 런타임에 타입을 확인하여 최적의 알고리즘을 사용하라

제네릭 타입 Generic Type Definition : 타입을 제네릭의 형태로 정의하는 것 Closed Generic Type : 타입 매개변수에 구체적인 타입을 지정한 경우 Open Generic Type : 여러 타입 매개변수 중 일부만 구체적인 타입을 지정한 경우 제네릭 타입의 타입 매개변수가 Value 타입일 때 장점 박싱과 언박싱을 피할 수 있다. 코드와 데이터의 크기가 줄어들고 성능이 개선된다. 컴파일러가 타입 매개변수에 대한 타입 안정성을 보장해준다. 런타임에 타입 유형을 매번 확인할 필요가 없다. 제네릭 타입의 장점 타입 매개변수에 새로운 타입을 지정하여 손쉽게 재사용할 수 있다. 타입 매개변수에 새로운 타입을 지정 = 유사한 기능을 가진 새로운 타입을 생성 타입, 메서드 제네릭화의 단..

개발공부/C# 2021.11.25

[Effective C#] 아이템 18 : 반드시 필요한 제약 조건만 설정하라

제약 조건을 사용하는 이유 타입 매개변수로 어떤 타입을 지정할 것인지 추가 정보가 제공되어 있지 않을 때, 컴파일러는 System.Object가 제공하는 기능만 사용할 수 있다. 그런데 제약 조건을 설정하면 컴파일러는 System.Object에 정의된 public 메서드보다 더 많은 것을 타입 매개변수에 기대할 수 있다. 제약 조건의 장점 제네릭 타입을 잘못 사용하는 경우 컴파일러가 그 사실을 알려줄 수 있다. 런타임 오류를 줄일 수 있다. 오용 가능성을 낮출 수 있다. 제약 조건이 컴파일러에게 주는 도움 컴파일러는 타입 매개변수로 전달된 타입이 제약 조건으로 설정한 기능을 모두 구현하고 있을 것이라고 가정할 수 있다. 컴파일러는 제네릭 타입을 사용하는 사용자가 타입 매개변수로 올바른 타입을 지정했는지 ..

개발공부/C# 2021.11.24

[Effective C#] 아이템 17 : 표준 Dispose 패턴을 구현하라

Dispose 란? 비관리 리소스를 해제하기 위해 사용하는 함수 비관리 리소스란? 메모리가 아닌 시스템 자원을 말한다. (ex. 윈도우 핸들, 파일 핸들, 소켓 핸들 등) 관리 리소스란? 메모리처럼 쓰이는 자원 (ex. new List() 등) 표준 Dispose 패턴이란? IDisposable 인터페이스로 Dispose를 구현한다. Dispose 내부에서는 비관리 리소스를 해제한다. 사용자가 Dispose를 사용하지 않을 경우를 대비해서 finalizer를 구현한다. finalizer에서 비관리 리소스를 해제한다. 위 조건을 구현한 Dispose를 표준 Dispose 패턴이라고 한다. IDisposable 란? 비관리 리소스를 정리하는 표준화된 방법. 최종 사용자에게 적시에 리소스를 해제할 수 있는 메..

개발공부/C# 2021.11.23

[Effective C#] 아이템 7 : 델리게이트를 이용하여 콜백을 표현하라

콜백이란? 나중에 실행할 함수를 아규먼트로 다른 함수에게 전달하는 것. 함수를 실행할 때 호출한다(call)는 표현을 사용하므로 나중에(back) + 호출한다(call)이 조합되어서 callback이라고 한다. 서버가 클라이언트에게 비동기적으로 피드백을 주기 위해 사용하는 방법이다. 콜백을 위해 멀티스레딩 기술도 사용되고, 동기적으로 상태를 갱신하는 기법도 활용된다. C#에서 콜백은 델리게이트를 이용하여 표현한다. 델리게이트 메서드를 다른 메서드로 전달하기 위해 만들어진 것. 즉, 메서드를 전달한다! 델리게이트 장점 타입 안정적인 콜백을 정의할 수 있다. 클래스 간의 결합도를 낮춘다. 콜백을 사용해야 하는 클라이언트를 단순하게 구성할 수 있다. 런타임에 콜백 함수를 구성할 수 있다. 하나의 델리게이트에 ..

개발공부/C# 2021.11.22

[Effective C#] 아이템 6 : nameof() 연산자를 적극 활용하라

nameof() 란? 임의의 기호(형식, 멤버, 변수 등)의 이름에 해당하는 문자열을 돌려주는 연산자. 심볼의 이름을 평가하며 타입, 변수, 인터페이스, 네임스페이스에 대해 사용할 수 있다. 완전히 정규화된 이름, 정규화되지 않은 이름 모두 제한 없이 사용할 수 있다. 다만, 제네릭 타입을 사용할 때는 부분적으로 제작이 있어 모든 타입 매개 변수를 지정한 닫힌 제네릭 타입만 사용할 수 있다. 제네릭 타입 열린 타입 : 아직 결정되지 않은 타입 파라미터가 존재. (ex. Dictionary) 닫힌 타입 : 모든 파라미터가 정해진 경우. (ex. Dictionary ) 장점 Visual Studio에서 기호 참조를 이해할 수 있기 때문에, 해당 기호의 이름을 바꾸면 그에 대한 모든 참조의 이름도 바뀐다. (..

개발공부/C# 2021.11.21