C#에서 enum값은 레퍼런스 타입이 아니다. 때문에 평소에 이리저리 값을 넘기고 받을 때 동적할당, 박싱/언박싱에대한 죄책감을 느끼지 않으며 쓰고 있었다. 하지만 알고보니 enum이 Dictionary의 키값으로 쓰이게 되면, Dictionary 내부에서 키값들이 같은지 비교할 때 enum을 박싱하면서 쓰레기가 생기게 된다.
예를 들면 이렇게
enum SomeType
{
None,
Gold,
Point,
Cash,
}
Dictionary<SomeType, String> type2Asdf = new Dictionary<SomeType, String>();
별 생각없이 Key자리에 enum을 넣어 왔었는데. 이렇게 하면 Dictionary내부에 쓰레기가 생긴다.
Dictionary에서는 키값이 같은지 여부를 판별할때 IEqualityComarer라는 인터페이스를 사용한다. 따로 Dictionary에 비교자 객체를 집어넣지 않는 한, 이 비교자 객체의 기본값은 EqualityComparer<T>.Default가 된다. 링크로 걸려있는 MSDN 문서에 의하면, 저 Default
프로퍼티는 T
타입이 System.IEquatable<T>
을 따로 구현하지 않았을 경우에 EqualityComparer<T>
를 반환하는데, 얘는 Object.Equals
와 Object.GetHashCode
을 기본 비교 함수들로 사용한다고 한다.
다른 primitive 타입들은 IEquatable
을 구현해놓은 반면에 enum은 구현해 놓지 않아서 비교하는데 Obejct.Equals
를 쓰게되고, 여기에서 enum을 Object로 박싱하게되니 쓰레기가 생기게 된다. struct도 같은 이유.
해결책은 간단하게 저 비교자 인터페이스를 하나 구현해서 Dictionary에게 넘겨주면 된다.
// 비교자 함수 객체
public struct SomeTypeComparer : IEqualityComparer<SomeType>
{
public bool Equals(SomeType a, SomeType b) { return a == b; }
public int GetHashCode(SomeType a) { return (int)a; }
}
// 생성자로 넘겨주자
Dictionary<SomeType, String> type2Asdf = new Dictionary<SomeType, String>(new SomeTypeComparer());
아니면 그냥 그냥 int를 써버리던가..
References
- https://stackoverflow.com/questions/26280788/dictionary-enum-key-performance
- http://beardseye.blogspot.kr/2007/08/nuts-enum-conundrum.html
'Note' 카테고리의 다른 글
TIL: 스칼라(jvm)에서 JS코드 실행하기 (0) | 2017.10.09 |
---|---|
TIL: 코루틴(Coroutine)에 대해 몇 가지 (0) | 2017.07.10 |
TIL: docker 컨테이너안에서 ip 바인딩은 localhost가 아니라 0.0.0.0으로 해야한다 (0) | 2017.07.02 |
TIL: Unity compares Objects to null implicitly (0) | 2017.06.29 |
TIL: git --fixup, --autosquash (0) | 2017.06.23 |