c# List 잔기술들 2

BindingList로 바꾸기

예를 들어 iEnumerable을 리스트로 만들려면 toList를 이용할 수 있는데 toBindingList는 없다. List로 만든 뒤 BindingList로 타입캐스트를 하려 해도 되질 않는다. 이런 경우를 위해 BindingList는 아래와 같은 컨스트럭터를 제공한다.

List<int> ints1 = new();
BindingList<int> ints2 = new(ints1);

Remove와 RemoveAt의 성능 비교

Remove는 인스턴스로 찾아서 지우고 RemoveAt은 인덱스 번호로 찾아서 지운다. 후자가 많이 더 빠르다. 지울 대상의 인덱스 번호를 안다면 당연히 후자를 써야 한다.

array, ArrayList, Dictionary와의 비교

1차원 배열은 List와 같다. 이들은 모두 메모리에 연속적으로 저장된다. 연속적으로 저장된다는 것은 일단 만들어진 상태에서 읽고 쓸 때 높은 효율을 낼 수 있지만 중간에 넣고 빼거나 앞뒤에 더하고 없앨 때 난처해진다. 크기가 달라지면 그 만큼의 연속적인 메모리를 찾아 확보해야 하기 때문이다. 이 과정에서 통째로 복사되며 오버헤드가 생긴다. 중간에서 일부를 뺄 때에는 그나마 빠진 값 이후에 대해서만 한꺼번에 앞으로 당기는 작업이 이뤄지겠지만 이 역시 부담스러운 건 마찬가지다. 배열에 아이템을 더할 땐 concatconcatenate 사슬처럼 잇다로 하고 리스트는 add 등으로 더 쉽게 한다. 전자는 linq를 이용하므로 더 느리다. 길이를 늘려야 할 때에는 List를 쓰는 게 정석이다.

ArrayList는 신경 쓸 필요 없이 그냥 쓰지 않으면 된다. 딕셔너리는 해쉬 테이블을 이용하므로 key를 이용하여 액세스할 때 O(1)에 가깝다. List 엘리먼트를 인덱스 번호로 찾아 들어가는 거처럼 한 방에 된다는 뜻이다. 엘리먼트에 랜덤 액세스를 해야 할 일이 많을 때 키를 이용할 수 있으면 딕셔너리가 좋고 인덱스 번호를 알 때에는 리스트가 더 좋다. 그러나 대부분 전자의 경우지 수 많은 엘리먼트들의 인덱스 번호를 일일이 알 수는 없으므로 랜덤 액세스를 많이 해야 할 때에는 일반적으로 딕셔너리를 쓴다.