2009-09-16 3 views
5

Visual Studio 2008 (C#)에서 작업 ... List 컬렉션을 사용하여 내 사용자 정의 클래스 (Shift)의 인스턴스를 저장합니다.List <T> .Remove()는 항상 목록의 첫 번째 객체를 삭제합니다.

Remove 메서드를 사용하여 목록에서 특정 시프트를 삭제하려고합니다.

그러나 List.Remove()는 항상 찾은 첫 번째 항목을 삭제합니다.

필자는 Shift 키를 사용하여 IComparable 인터페이스를 구현했지만이 방법으로 충분하다고 생각한 다음 IEqualityComparer 구현을 추가했지만 여전히 효과가 없습니다. 여기

내 구현 발췌입니다 :

지역에서 IComparable 회원

public int CompareTo(object obj) 
    { 
     Shift s1 = this; 
     Shift s2 = (Shift)obj; 
     if (s1.start.time != s2.start.time) 
      return s1.start.CompareTo(s2.start); 
     else 
      return s1.end.CompareTo(s2.end); 
    } 

endregion

지역 IEqualityComparer 회원

public bool Equals(Shift x, Shift y) 
    { 

     if ((x.opening) != (y.opening)) return false; 
     if ((x.closing) != (y.closing)) return false; 
     if (!x.opening) if (x._start != y._start) return false; 
     if (!x.closing) if (x._end != y._end) return false; 
     if (x.when != y.when) return false; 
     if (x.day != y.day) return false; 
     if (x.EmployeeID != y.EmployeeID) return false; 
     return true; 
    } 

    public int GetHashCode(Shift obj) 
    { 
     return obj.ToString().ToLower().GetHashCode(); 
    } 

endregion

아직까지도, 목록에 두 교대가있을 경우 "8:00 - 15:00"; "12:00 - 16:00", 제거 ("12 : 00-16 : 00") 결과는 "8:00 - 15:00"에 제거되고 후자는 콜렉션에 남아 있습니다!

여기에 무슨 문제가 있습니까? 당신은 object.GetHashCodeobject.Equals을 무시할 수 있습니다 들으

답변

11

:

public override bool Equals(object obj) 
{ 
    if(obj == null) 
    { 
     return false; 
    } 
    return Equals(this, obj as Shift); 
} 

public override int GetHashCode() 
{ 
    return this.GetHashCode(this); 
} 

당신은 아마 Equals(x, y)에서 널 체크를해야한다.

+0

obj.GetType()! = GetType() 인 경우 false를 반환해야합니다. 그렇지 않으면보다 정교한 알고리즘을 가질 수있는 하위 클래스에 대한 등호 검사를 수행 할 위험이 있습니다. –

+0

-1, 그는 object.GetHashCode()를 오버로드하지 않았으며 IEqualityComparer .GetHashCode (T)를 구현했습니다. –

+0

@csharptest 좋은 지점, 감사합니다 –

0

EqualityComparer<T>.Default을 제거하여 동일성을 확인하고 제거 할 객체를 선택하십시오. 객체에 구현 된 경우 IEquatable<T>을 사용합니다. 그렇지 않으면 참조 평등을 사용합니다.

당신은 당신이 원하는 행동을 얻을 수있는 두 가지 옵션이 있습니다

1) 시프트 IEquatable<T>이 (단지 Object.Equals를 무시하거나 방법을 만들지 만, 시프트하지 구현합니다 - Shift : IEquatable<Shift>를)

2) 사용 제공된 예와

0

List<T>.RemoveAt, 당신은 전화하는거야 :

List<Shift>.Remove("12:00 - 16:00"); 

01 이 경우은 String 값이며 실제 Shift 개체는 아닙니다. CompareTo 메소드에서 코드가 String 값을 Shift 오브젝트로 올바르게 캐스팅하고 있는지 확인하십시오. 그렇지 않으면, 시작 시간을 비교할 때 ... 일들이 엉망이 될 수 있습니다.

+0

저스틴, 실제로 문자열 매개 변수를 전달하지는 않습니다. 이것은 개념을 보여주기위한 부분에서 "의사 코드"의 일종입니다. 죄송합니다. 모호한 경우 –

3

IComparable은 평등을 비교하는 데 일반적으로 사용되지 않으므로 (주문시 사용됨) List<T>.Remove()은이를 무시합니다.

IEqualityComparer은 동등한 목적으로 IComparable과 동일하지 않습니다. comparer 오브젝트에 의해 구현되는 것으로 가정합니다. 즉, 다른 오브젝트을 비교하는 오브젝트입니다. 평등 비교가 클래스에 내재하기를 원하면 IEquatable<T>을 구현해야합니다. 또는 인터페이스를 구현하지 않고 클래스에 Object.Equals()Object.GetHashCode()을 무시하십시오.

+0

실제로 Object.Equals()가 올바르게 작동합니다. 그것은 모두의 가장 간단한 옵션처럼 보입니다. 고맙습니다 –