.Contains () in einer Liste benutzerdefinierter Klassenobjekte

95

Ich versuche, die .Contains()Funktion für eine Liste benutzerdefinierter Objekte zu verwenden

Dies ist die Liste:

List<CartProduct> CartProducts = new List<CartProduct>();

Und die CartProduct:

public class CartProduct
{
    public Int32 ID;
    public String Name;
    public Int32 Number;
    public Decimal CurrentPrice;
    /// <summary>
    /// 
    /// </summary>
    /// <param name="ID">The ID of the product</param>
    /// <param name="Name">The name of the product</param>
    /// <param name="Number">The total number of that product</param>
    /// <param name="CurrentPrice">The currentprice for the product (1 piece)</param>
    public CartProduct(Int32 ID, String Name, Int32 Number, Decimal CurrentPrice)
    {
        this.ID = ID;
        this.Name = Name;
        this.Number = Number;
        this.CurrentPrice = CurrentPrice;
    }
    public String ToString()
    {
        return Name;
    }
}

Also versuche ich ein ähnliches Warenkorbprodukt in der Liste zu finden:

if (CartProducts.Contains(p))

Aber es ignoriert ähnliche Warenkorbprodukte und ich scheine nicht zu wissen, was es überprüft - die ID? oder alles?

Danke im Voraus! :) :)

Jan Johansen
quelle

Antworten:

119

Sie müssen implementieren IEquatableoder außer Kraft setzen Equals()undGetHashCode()

Beispielsweise:

public class CartProduct : IEquatable<CartProduct>
{
    public Int32 ID;
    public String Name;
    public Int32 Number;
    public Decimal CurrentPrice;

    public CartProduct(Int32 ID, String Name, Int32 Number, Decimal CurrentPrice)
    {
        this.ID = ID;
        this.Name = Name;
        this.Number = Number;
        this.CurrentPrice = CurrentPrice;
    }

    public String ToString()
    {
        return Name;
    }

    public bool Equals( CartProduct other )
    {
        // Would still want to check for null etc. first.
        return this.ID == other.ID && 
               this.Name == other.Name && 
               this.Number == other.Number && 
               this.CurrentPrice == other.CurrentPrice;
    }
}
Rowland Shaw
quelle
4
aber wo ist GetHashCode()?
Zionpi
1
Sie müssen GetHashCode () nicht implementieren. Es funktioniert ohne es.
user890332
140

Wenn Sie .NET 3.5 oder höher verwenden, können Sie LINQ-Erweiterungsmethoden verwenden, um eine "enthält" -Prüfung mit der AnyErweiterungsmethode zu erreichen :

if(CartProducts.Any(prod => prod.ID == p.ID))

Dadurch wird geprüft, ob ein Produkt vorhanden CartProductsist, dessen ID mit der ID von übereinstimmt p. Sie können einen beliebigen booleschen Ausdruck nach dem setzen =>, um die Prüfung durchzuführen.

Dies hat auch den Vorteil, dass sowohl für LINQ-zu-SQL-Abfragen als auch für In-Memory-Abfragen gearbeitet werden kann, wo Containsdies nicht der Fall ist.

Paul Turner
quelle
12

Es wird geprüft, ob das bestimmte Objekt in der Liste enthalten ist.

Verwenden Sie möglicherweise besser die Suchmethode in der Liste.

Hier ist ein Beispiel

List<CartProduct> lst = new List<CartProduct>();

CartProduct objBeer;
objBeer = lst.Find(x => (x.Name == "Beer"));

hoffentlich hilft das

Sie sollten sich auch LinQ ansehen - Overkill dafür vielleicht, aber dennoch ein nützliches Tool ...

Martin Milan
quelle
1
Wie kann Linq jemals übertrieben sein?
Mel Gerats
@MEL - Warum in eine Abfrage verwickelt werden und Inferenz für etwas so Einfaches eingeben? Das heißt, es könnte für jemanden besser lesbar sein, der nicht mit Lamdas vertraut ist ...
Martin Milan
+1 Gutes klares Beispiel, das die Option zeigt, die von Änderungen an anderer Stelle nicht betroffen wäre (dh wenn die Equals()Methode aus irgendeinem Grund geändert wurde)
Rowland Shaw
4

Standardmäßig haben Referenztypen Referenzgleichheit (dh zwei Instanzen sind nur dann gleich, wenn sie dasselbe Objekt sind).

Sie müssen überschreiben Object.Equals(und Object.GetHashCodeübereinstimmen), um Ihre eigene Gleichheit zu implementieren. (Und es ist dann eine gute Praxis, einen Gleichheitsoperator zu implementieren ==.)

Richard
quelle
1
Warum Object.Equals überschreiben, was an anderer Stelle im Code Konsequenzen haben könnte? Für mich ist es sinnvoller, den Suchcode entsprechend zu ändern und nicht die zugrunde liegende Objektklasse, nach der gesucht wird ...
Martin Milan
Haben Sie einige Beispiele dafür, .Find () oder das Überschreiben von Object.Equals / GetHashCode?
Jan Johansen
@Martin IT wäre sehr kaputt, wenn Sie möchten, dass sich der Vergleich zweier CartProductObjekte an verschiedenen Orten unterschiedlich verhält.
Rowland Shaw
1
@Rowland - Aber ich sage nicht, dass er ändern müsste, wie ein Vergleich funktioniert. Wenn er ein bestimmtes Objekt haben möchte, verwenden Sie Contains (). Wenn er möchte, dass ein Objekt einem bestimmten Kriterium entspricht, verwenden Sie Find () mit einem geeigneten Prädikat (Lamda-Ausdruck) ... Ich argumentiere tatsächlich, dass Sie den Vergleichscode überhaupt nicht berühren - Sie rufen einfach die richtige Methode für das auf Liste für die Aufgabe, die Sie zu erfüllen versuchen ...
Martin Milan
1
@Martin scheint, ich habe Ihren Kommentar falsch interpretiert, um etwas im Sinne von "Überschreiben Contains()" zu sein. Stimmen Sie zu, dass Find()das Problem gelöst werden könnte, obwohl ich vorschlagen würde, dass eine geeignete Gleichheitsmethode in vielen anderen Fällen nützlicher ist, da das OP nicht feststellte, dass die Referenzen für zwei Instanzen derselben Entität unterschiedlich waren.
Rowland Shaw
1

Sie müssen ein Objekt aus Ihrer Liste erstellen, wie:

List<CartProduct> lst = new List<CartProduct>();

CartProduct obj = lst.Find(x => (x.Name == "product name"));

Dieses Objekt erhält die Suche nach dem gesuchten Wert anhand seiner Eigenschaften: x.name

Dann können Sie List-Methoden wie Contains oder Remove verwenden

if (lst.Contains(obj))
{
   lst.Remove(obj);
}
José Chávez
quelle
0

Implementieren override Equals()undGetHashCode()

public class CartProduct
{
    public Int32 ID;
    ...

    public CartProduct(Int32 ID, ...)
    {
        this.ID = ID;
        ...
    }

    public override int GetHashCode()
    {
        return ID;
    }

    public override bool Equals(Object obj)
        {
            if (obj == null || !(obj is CartProduct))
                return false;
            else
                return GetHashCode() == ((CartProduct)obj).GetHashCode();
        }

}

gebraucht:

if (CartProducts.Contains(p))
A. Morel
quelle
-1

Wenn Sie die Kontrolle darüber haben möchten, müssen Sie die [IEquatable-Schnittstelle] [1] implementieren.

[1]: http: // Diese Methode ermittelt die Gleichheit mithilfe des Standardgleichheitsvergleichs, der durch die Implementierung der IEquatable.Equals-Methode für T (den Wertetyp in der Liste) durch das Objekt definiert wird.

Gerrie Schenck
quelle