2013-03-05 4 views
0

List에서 상속하지만 List.Contains가 느리기 때문에 속도가 느린 C# 라이브러리 클래스가 있습니다. 많은 클라이언트 코드가이 클래스에 의존하고 인터페이스를 변경하는 데 너무 복잡하기 때문에 Dictionary 또는 HashSet과 같은 클래스에서 상속하도록 클래스를 변경할 수 없습니다. 이 방법을 변경하지 않고 속도를 낼 수있는 쉬운 방법이 있습니까? 목록 중 일부는 매우 커서 우리는 메모리에 두 개의 사본이 필요하지 않습니다. List의 모든 메소드를 오버라이드하고 싶지는 않습니다.속도 향상 list.contains

public class UniqueList<T> : List<T>, IList<T> 
{ 
    public new void Add(T item) 
    { 
     if (!this.Contains(item) && item != null) 
     { 
      base.Add(item); 
     } 
    } 
+2

수업은 매우 문제가 있습니다. 누군가가 UniqueList의 컴파일 타임 타입을 사용하지 않고'List '또는'IList '을 사용하면'new' 때문에'Add' 메소드가 사용되지 않습니다 –

+0

당신이 옳았습니다. 의도적 인 것이 아니 었습니다 (나는 쓰지 않았습니다). 아무도 그렇게하기를 원하지 않는 사람이있을 수 있다고 불평하지 않았기 때문입니다. –

답변

0

당신은 클래스 수준의 개인 사전을 가지고 있고 그 다음 목록에 가서 확인 사전에 발견되지 않는 경우는 먼저 사전에 확인하실 수 있습니다, 자사의 최적화는 순수 솔루션을 토륨되지도 당신을 비용 목록에서 상속 추가 메모리가

+0

문제는 목록 중 일부가 매우 길고 메모리의 차이가 상당 할 수 있다는 것입니다. –

+0

다른 접근 방법을 알고 싶습니다. – TalentTuner

2

당신이 당신의 클래스가 클라이언트 코드

List.Contains를 사용하는 방법에 대한 제어를하지 않는 아주 나쁜 생각입니다 O (n)이 작업입니다. Dictionary.ContainsKey는 O (1)이므로 Dictionary를 사용하는 것이 가장 좋은 조언이라고 생각합니다. 그러나 실제로 사용하지 않으려는 경우 목록을 정렬하여 보관하는 것이 좋습니다. O (로그 요소가 목록에 이미있는 경우 n)의

public void Add(T item) 
{ 
    int index = BinarySearch(item); 
    if (index < 0) 
    { 
     Insert(~index, item); 
    } 
} 

은 BinarySearch는 인덱스를 반환합니다. 요소가 목록에없는 경우 BinarySearch 메서드는 이진 검색 메서드에 전달한 요소보다 큰 첫 번째 요소의 인덱스를 이진수로 나타내는 음수를 반환합니다. 이 T가 될 수 있는지에 따라 같은 시나리오에서 가능하지 않을 수도 있습니다 BinarySearch를 사용

: http://msdn.microsoft.com/en-us/library/w4e7fxsh.aspx

이 방법은 목록 요소의 순서를 결정하는 타입 T에 대한 기본 비교의 Comparer.Default를 사용합니다. Comparer.Default 속성은 형식 T가 IComparable 제네릭 인터페이스를 구현하는지 여부를 확인하고 사용 가능한 경우 해당 구현을 사용합니다. 그렇지 않은 경우 Comparer.Default는 형식 T가 IComparable 인터페이스를 구현하는지 여부를 확인합니다. 형식 T가 두 인터페이스 중 하나를 구현하지 않으면 Comparer.Default는 InvalidOperationException을 throw합니다. 당신이 List<>에서 상속하고 있기 때문에 짧은 호에서

+0

좋습니다. 문제는 내 "목록"의 동작이 변경되어 항목이 추가 된 순서와 다른 순서로 반환된다는 것입니다. 내 클래스가 동일하게 동작하지만 실제로 구현시에만 다른 점이 있으므로 목록과 비슷한 동작이 필요합니다. –

2

당신은 본질적으로 그림자 할 경우에도 때문에이 방법에 UniqueList을 통과하는 클라이언트 코드를 중지 할 수 없습니다 방법을 포함, 끝장 List<>을 허용하는 경우 새 Contains를 숨기고 기존 Contains를 사용합니다.

List<>에서 상속을 제거하고 자신 만의 Contains를 구현하고 필요한 모든 메서드를 목록에서 다시 구현해야합니다 (내부적으로 저장을 위해 private List<>을 사용할 수 있으며 필요에 따라 간단히 위임 할 수 있음).),이 변경이 중단되는 모든 코드를 수정하십시오.

당신이 일을 해치는 동안 인터페이스에 대한 개발을 촉진하는 C5 컬렉션 클래스를 살펴보고이 문제에 부딪치지 않게 할 수 있습니다. (나는 알고 있습니다. 말을 풀면 더 많은 헛간 문이 닫힙니다)

나는 이것이 당신이 찾고있는 대답이 아니라는 것을 알고있다. 그러나 당신이 원하는 대답을 얻지 못할 것이다. (실제로 이것을 프로그램 할 방법이 없다. Castle Interceptors과 같은 것을 시도 할 수있다. 그들이이 경우에 일할 것이라고 생각하지 마십시오.그러나 그 때 나는 그들이 확실하지 않을 것이라는 점을 확신 할 수 없다)

다시, 실제로 도움을 줄 수없는 것에 대해 사과드립니다.