[Effective C# Item 12] 할당 구문보다 멤버 초기화 구문이 좋다 C# 코딩을 하다보면 클래스를 생성할 때 생성자를 2개 이상 작성해야 할 경우도 있다. 이 때 생성자 내에서 멤버 변수들의 값을 초기화하도록 코딩하다 보면 모든 생성자에서 초기화를 해줘야 하는데 자칫 멤버 변수 초기화 코드가 누락될 수 있다. 이런 실수를 하지 않으려면 멤버 초기화 구문(member initializer)를 사용하는 것이 좋다. 멤버 초기화 구문(member initializer) public class MyClass { // 컬렉션을 선언하는 동시에 초기화 private List labels = new List(); } 위 예제가 바로 멤버 초기화 구문이다. 위와 같이 코딩을 하면 MyClass 타입..
[Effective C# Item 11] .NET 리소스 관리에 대한 이해 .NET 의 가비지 콜렉터의 동작 방식을 잘 알아야 하고, 비관리 리소스를 어떻게 다룰지에 대해서도 정확히 이해해야 한다. 가비지 콜렉터 가비지 콜렉터는 관리되는 메모리를 관장하며 네이티브 환경과는 다르게 메모리 누수, 댕글링 포인터, 초기화되지 않는 포인터, 다른 메모리 관리 문제를 개발자들이 직접 다루지 않도록 자동화해준다. 가비지 콜렉터가 메모리 전반적으로 관리해주기 때문에 개발자는 응용프로그램의 구조를 단순하게 유지할 수 있다. 가비지 콜렉터의 마크/콤팩트(Mark/Compact) 알고리즘은 여러 객체 사이의 연관 관계를 효율적으로 파악하여 더 이상 사용되지 않는 객체를 자동으로 제거한다. 가비지 콜렉터가 수행되..
[Effective C# Item 10] 베이스 클래스가 업그레이드된 경우에만 new 한정자를 사용하라 베이스 클래스에서 virtual로 선언하지 않은 멤버를 재정의하려는 경우에 new 한정자를 사용해서 재정의할 수 있다. 허나 사용할 수 있는 것과 잘 사용하는 것은 전혀 다른 이야기다. 모든 프로그래밍에서 그렇듯 안 될 거 같은 것을 억지로 바꾸려할 경우에는 사용하는 데 있어서 신중해야 한다. 앞의 Item 9의 박싱과 언박싱도 그 예중 하나다. virtual로 선언되지 않은 메서드를 new 한정자로 억지로 재정의하면 메서드의 동작 방식을 모호하게 만들 우려가 있기 때문이다. 엉? 왜 동작이 다른거야? object c = MakeObject(); // MyClass 타입의 참조를 이용하여 메서드..
[Effective C# Item 9] 박싱과 언박싱을 최소화하라 Value 타입은 주로 값을 저장할 때 쓰는 저장소이며 다형적이지 못하다. 그리고 System.Object는 .NET 프레임워크에서 모든 타입의 최상위 타입으로 정의하고 있는데 언뜻 보면 Value 타입과 System.Object는 양립하지 못하는 것처럼 보인다. 하지만 .NET 프레임워크는 박싱과 언박싱이라는 방법을 통해서 두 타입을 서로 변환하게 해준다. 박싱과 언박싱(Boxing and Unboxing) 박싱 : Value 타입의 객체를 타입이 정해져 있지 않은 임의의 참조 타입 내부에 포함시키는 방법 언박싱 : 박싱되어 있는 참조(reference) 타입의 객체로부터 Value 타입 객체의 복사본을 가져오는 방법 이런 박..
[Effective C# Item 8] 이벤트 호출 시에는 null 조건 연산자(?.)를 사용하라 이벤트를 발생 시키는 작업은 언뜻보면 그저 단순한 작업에 불과하다고 생각할지 모른다. 하지만, 이벤트에 결합된 이벤트 핸들러가 없다면 NullReferenceException이 발생한다. 이를 해결하기 위해서 이벤트 핸들러가 결합되어 있는지 확인하는 코드를 추가해주면 된다. 하지만 또 문제가 발생할 수 있다. 이벤트 핸들러의 유무 확인 후에 다른 스레드에서 이벤트 핸들러 처리에 관한 작업이 실행될지도 모르기 때문이다. 다음 예제를 통해서 더 자세히 알아보자. 간단한 이벤트 발생 코드 public class EventSource { private EventHandler Updated; public ..
7) 델리게이트를 이용하여 콜백을 표현하라 콜백을 설명하기 위한 간단한 대화로 시작해보자. 공장장 : "기모씨, 제가 공장 둘러보는 동안 A 공정 파트 좀 민수씨가 맡아 주고 전화로 상태 보고해주세요~" 안기모 : "공장장님, 우선 A-1 공정 끝냈습니다." 안기모 : "공장장님, A-2 공정 끝냈습니다." 안기모 : "공장장님, A-3 공정 을 위한 기계가 고장났습니다." 공장장 : "아 그래요? 제가 설비 관리 팀에 문의 넣어 놓을게요." 잠시후 안기모 : "공장장님, A 공정 완료했습니다." 공장장은 안기모씨에게 A 공정이라는 일을 시켰고 안기모씨는 여러 차례에 걸쳐 공장장에게 일 상태를 보고했다. 공장장은 공장 여러 곳을 둘러보다가도 잠깐씩 A공정의 상태를 같이 체..
6) nameof() 연산자를 적극 활용하라 분산 시스템이 널리 활용되면서 서로 다른 플랫폼, 언어로 개발된 프로그램들 사이에서도 데이터를 주고 받을 일이 많아졌다. 이런 차이를 극복하기 위해서 이름이나 string 식별자에 의존하는 라이브러리들이 많이 사용된다고 한다. 하지만 이런 방식은 간편할지라도 여러가지 단점이 생기곤 하는데, 가장 대표적인 단점이 타입 정보를 손실한다는 것이다. 이로 인해서, 타입 정보를 활용해서 추가 기능을 제공하는 개발 도구를 쓰는데 어려움을 겪고, 정적 타입 언어이 주요 장점을 상실한다. 그래서 C# 설계팀은 C# 6.0에 nameof()라는 연산자를 추가했다. 이 키워드는 심볼 그 자체를 해당 심볼을 포함하는 string으로 대체해준다. name of 연산자를 ..
5) 문화권별로 다른 문자열을 생성하려면 FormattableString을 사용하라 앞선 보간 문자열을 다루는 글에서 문자열 보간 기능을 이용해서 가독성 좋은 string 생성 방법을 배웠다. 하지만 여러 문화권과 다양한 언어를 다뤄야 하는 경우에는 좀더 세부적인 제어가 필요하기 때문에 문자열을 생성하는 과정을 조금 더 자세히 알아둬야 한다. 앞의 글에서 다뤘듯이, 문자열 보간 기능을 이용해서 string을 생성할 경우 아래 코드와 같이 선두에 '$'를 붙이고 중괄호 { }를 사용해서 string을 생성하는 것이 전부다. 근데 특이한 것은 이 보간 기능의 결과로 생성되는 반환값의 타입이 string일 수도 있지만 FormattableString을 상속하는 타입일 수도 있다. string fir..