2009-09-16 6 views
5

Arbeiten in Visual Studio 2008 (C#) ... ich eine Liste Sammlung verwende Instanzen meiner benutzerdefinierten Klasse zu speichern (Shift).C# - Liste <T> .Remove() löscht immer das erste Objekt auf der Liste

Ich möchte eine bestimmte Verschiebung aus der Liste löschen, indem Sie die Remove-Methode verwenden.

Aber List.Remove() löscht immer das erste Element, das es findet.

Ich habe die IComparable-Schnittstelle für meine Schicht implementiert, ich dachte, das wäre genug, dann habe ich eine Implementierung von IEqualityComparer hinzugefügt, und es hat immer noch keinen Effekt.

Hier ist der Auszug mit meiner Implementierung:

Region IComparable Mitglieder

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

Region IEqualityComparer Mitglieder

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

Und dennoch, wenn die Liste zwei Schichten enthält, sagen Sie "8:00 - 15:00"; "12:00 - 16:00" ruft "Entfernen" ("12: 00-16: 00") auf "8:00 - 15:00" wird entfernt, und letzteres bleibt in der Sammlung!

Was ist hier falsch? Thx

Antwort

11

Sie überschreiben können object.GetHashCode und object.Equals:

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); 
} 

sollten Sie auch tun, wahrscheinlich eine Null-Check-in Equals(x, y).

+0

Sie sollten auch false zurückgeben, wenn obj.GetType()! = GetType(), andernfalls riskieren Sie, Gleichheitsprüfungen gegen Unterklassen, die verfeinerte Algorithmen haben können. –

+0

-1, Er überladen object.GetHashCode() nicht, er implementiert IEqualityComparer . GetHashCode (T). –

+0

@csharptest good spot, danke –

0

Entfernen verwendet EqualityComparer<T>.Default zum Ermitteln der Gleichheit und wählen Sie, welches Objekt zu entfernen, die IEquatable<T> verwenden, wenn es auf Ihrem Objekt implementiert ist, andernfalls wird es Referenzgleichheit verwenden.

Sie haben zwei Möglichkeiten, das Verhalten Sie wollen zu bekommen:

1) behelfen implementieren IEquatable<T> (nicht nur Object.Equals außer Kraft setzen oder die Methode, sondern Umschalt machen - Shift : IEquatable<Shift>)

2) Verwenden Sie List<T>.RemoveAt

0

Mit dem Beispiel, das Sie zur Verfügung gestellt, die Sie anrufen:

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

"12:00 - 16:00" In diesem Fall ist ein String Wert und kein tatsächliches Shift Objekt. Stellen Sie sicher, dass in Ihrer CompareTo-Methode, dass Ihr Code den String-Wert korrekt an ein Shift-Objekt überträgt. Ansonsten, wenn es Startzeiten vergleicht ... könnten die Dinge drunter und drüber gehen.

+0

Justin, in der Tat übergebe ich nicht wirklich einen String-Parameter, das war eine Art "Pseudo-Code" von meinem Teil, nur um das Konzept zu zeigen. Sorry wenn das mehrdeutig war –

3

IComparable wird normalerweise nicht verwendet, um für Gleichheit zu vergleichen (es wird für die Bestellung verwendet), so ignoriert List<T>.Remove() es.

IEqualityComparer entspricht nicht IComparable für Gleichstellungszwecke. Es soll durch ein Vergleichsobjekt implementiert werden - das heißt, ein Objekt, das andere Objekte auf Gleichheit vergleicht. Wenn Gleichheitsvergleiche für Ihre Klasse inhärent sein sollen, müssen Sie eher IEquatable<T> implementieren. Oder überschreiben Sie einfach Object.Equals() und Object.GetHashCode() in Ihrer Klasse, ohne irgendwelche Schnittstellen zu implementieren.

+0

Eigentlich funktioniert Object.Equals() genau richtig! Das scheint die einfachste Option von allen zu sein. Vielen Dank –

Verwandte Themen