2014-02-07 13 views
5

Ich habe eine Klasse "Class1", die eine Zeichenfolgenvariable "sText" in .NET 2.0 hat. Ich habe eine Liste von Objekten dieser Klasse "lstClass1" erstellt. Es speichert viele Objekte dieser Klasse nach dem Setzen der String-Variablen.List.Contains schlägt auf Objektvergleich fehl

komplette Code ist:

public partial class Form1 : Form 
{ 
    public Form1() 
    { 
     InitializeComponent(); 
    } 

    private void button1_Click(object sender, EventArgs e) 
    { 
     if (!lstClass1.Contains(new Class1("text1"))) 
      lstClass1.Add(new Class1("text1")); 
    } 

    public List<Class1> lstClass1 = new List<Class1>(); 
} 

public class Class1 
{ 
    public Class1(string sText) 
    { 
     this.sText = sText; 
    } 

    public string sText = ""; 
} 

Nun, das Problem ist, dass ich nur Klassenobjekte hinzufügen möchten, die Zeichenfolge mit eindeutigen Textwert hat. Wenn beispielsweise lstClass1 bereits ein Objekt mit dem Zeichenfolgenvariablenwert "text1" enthält, sollte das Hinzufügen eines Objekts, das auch "text1" enthält, nicht zulässig sein. So schrieb ich Code:

if (!lstClass1.Contains(new Class1("text1"))) 
    lstClass1.Add(new Class1("text1")); 

Aber es erlaubt immer der Text „text1“ noch hinzugefügt werden, wenn es bereits ein Objekt in der Liste mit „text1“ string. Meine Annahme war, dass beim ersten Buttonklick-Ereignis "button1_Click" das Objekt hinzugefügt wird, da die Liste leer ist, aber beim nächsten Klick auf die List.Contains-Funktion prüft, ob sich bereits ein Objekt in der Liste mit der String-Variablen "text1" befindet Wenn es gefunden wird, wird es nicht hinzugefügt. Aber es erlaubt immer ein Objekt mit dem Text "text1" hinzuzufügen, auch wenn es bereits in der Liste vorhanden ist.

Bitte beachten Sie: Ich habe keine einfache Liste von Zeichenketten oder einer Zeichenkette genommen, weil ich mein großes Problem von Liste, Klassen und Objekten auf einfache Weise erklären möchte.

Bitte helfen.

+1

Haben Sie eine Implementierung der standardmäßigen Equals- und GetHashCode-Methoden von Class1 bereitgestellt? – Oscar

+0

http://stackoverflow.com/questions/10454519/best-way-to-compare-two-complex-object – k06a

+0

Nicht sicher, warum Sie diese 'neue Class1 (" text1 ")' nicht in einer neuen 'Class1 speichern '-typische Variable, BTW. Es gibt keine Notwendigkeit, es zweimal zu konstruieren. Einfach einmal konstruieren, auf die Variable prüfen und dann aus der Variablen speichern. – Nyerguds

Antwort

7

Verwenden Any() Methode:

if (!lstClass1.Any(x => x.sText == "text1")) 
    lstClass1.Add(new Class1("text1")); 

Dieser Code:

if (!lstClass1.Contains(new Class1("text1"))) 
    lstClass1.Add(new Class1("text1")); 

konnte nur funktionieren, wenn Sie die Equals() und GetHashCode() Methoden für Ihre Class1 bieten würde machen die Vergleiche zwischen zwei Objekten, dies zu ermöglichen Klasse. Um dies zu erreichen, sollte Ihre Klasse die IEquatable Schnittstelle implementieren. So könnte Ihr Class1 wie folgt aussehen:

public class Class1 : IEquatable<Class1> 
{ 
    public Class1(string sText) 
    { 
     this.sText = sText; 
    } 

    public string sText = ""; 

    public bool Equals(Class1 other) 
    { 
     if (other == null) 
     return false; 

     if (this.sText == other.sText) 
     return true; 
     else 
     return false; 
    } 

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

Dies schlägt fehl, da die Liste Equals auf die Instanz aufruft, und die Default-Implementierung hat einen Scheck für Referenz Gleichheit. Obwohl Ihr Objekt den Eigenschaftswert name hat, handelt es sich um eine Differenzinstanz, und daher sind die Referenzen nicht gleich.

In Class1 Überschreibung der Equals Methode, die zugrunde liegenden Eigenschaften

public override bool Equals(object other) 
{ 
    Class1 rhs=other as Class1; 
    if(rhs==null) return false; 

    return this.sText == rhs.sText; 
} 
0

Das Problem Sie konfrontiert sind hier zwischen Objekt und Instanz zu vergleichen. Wenn Sie nach dem Folgenden suchen, fragen Sie grundsätzlich "ist in der Sammlung?"

!lstClass1.Contains(new Class1("text1")) 

Nun, es ist offensichtlich nicht, da Sie es gerade erstellt haben. Was Sie überprüfen müssen, ist der Inhalt dieses Objekts. Dies ist am einfachsten, wenn Sie die Sammlung durchlaufen und nach dem Inhalt jedes Objekts suchen.

Dies ist sehr einfach mit LINQ zu tun (obwohl ich nicht sicher bin, dass es für .NET 2 verfügbar ist.0):

!lstClass1.Any(i => i.Text == "text1") 

Eine andere Lösung wäre, die GetHashCode() und Equals Methoden Ihrer Class1 zu überschreiben, um zwei Objekte zu betrachten als „gleich“, wenn deren Inhalt identisch sind. und erlauben so einen gründlichen Vergleich.

1

Enthält wird nur korrekt funktionieren, wenn Sie IEquatable in Ihrem Fall implementieren.

können Sie den folgenden Code verwenden statt:

public class Class1 //: IEquatable<Class1> 
{ 
    public string sText = ""; 
    public Class1(string sText) 
    { 
     this.sText = sText; 
    } 

    //public bool Equals(Class1 other) 
    //{ 
    // return this.sText == other.sText; 
    //} 
} 
static void Main(string[] args) 
{ 
    List<Class1> lstClass1 = new List<Class1>() { new Class1("text1") }; 
    if (!lstClass1.Contains(new Class1("text1"))) 
     lstClass1.Add(new Class1("text1")); 
    Console.WriteLine(lstClass1.Count); 
    Console.ReadKey(); 
} 

Kommentar- der kommentierten Zeilen und Sie werden den Unterschied sehen.