.Contains () sur une liste d'objets de classe personnalisés

95

J'essaye d'utiliser la .Contains()fonction sur une liste d'objets personnalisés

Voici la liste:

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

Et le 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;
    }
}

J'essaie donc de trouver un produit similaire dans la liste:

if (CartProducts.Contains(p))

Mais il ignore les produits de panier similaires et je ne semble pas savoir ce qu'il vérifie - l'ID? ou tout ça?

Merci d'avance! :)

Jan Johansen
la source

Réponses:

119

Vous devez mettre en œuvre IEquatableou remplacer Equals()etGetHashCode()

Par exemple:

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
la source
4
mais où est GetHashCode()?
zionpi
1
Vous n'avez pas besoin d'implémenter GetHashCode (). Cela fonctionne sans cela.
user890332 le
141

Si vous utilisez .NET 3.5 ou une version plus récente, vous pouvez utiliser les méthodes d'extension LINQ pour effectuer une vérification «contient» avec la Anyméthode d'extension:

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

Cela vérifiera l'existence d'un produit dans CartProductslequel a un ID correspondant à l'ID de p. Vous pouvez mettre n'importe quelle expression booléenne après le =>pour effectuer la vérification.

Cela a également l'avantage de fonctionner pour les requêtes LINQ-to-SQL ainsi que pour les requêtes en mémoire, alors que ce Containsn'est pas le cas.

Paul Turner
la source
12

Il vérifie si l'objet spécifique est contenu dans la liste.

Vous feriez peut-être mieux d'utiliser la méthode Find de la liste.

Voici un exemple

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

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

J'espère que cela pourra aider

Vous devriez également regarder LinQ - exagéré pour cela peut-être, mais un outil utile néanmoins ...

Martin Milan
la source
1
comment Linq peut-il jamais être exagéré?
Mel Gerats
@MEL - Pourquoi se mêler d'une requête et d'une inférence de type pour quelque chose d'aussi simple? Cela dit, il pourrait être plus lisible pour quelqu'un qui ne connaît pas les lamdas ...
Martin Milan
+1 Bon exemple clair, qui montre l'option qui ne serait pas affectée par des changements ailleurs (c'est-à-dire si la Equals()méthode a été modifiée pour une raison quelconque)
Rowland Shaw
4

Par défaut, les types de référence ont une égalité de référence (c'est-à-dire que deux instances ne sont égales que si elles sont le même objet).

Vous devez remplacer Object.Equals(et Object.GetHashCodefaire correspondre) pour implémenter votre propre égalité. (Et il est alors recommandé d'implémenter un ==opérateur d' égalité ,,.)

Richard
la source
1
Pourquoi remplacer Object.Equals, ce qui pourrait avoir des conséquences ailleurs dans le code? Pour moi, il est plus logique de modifier le code de recherche en conséquence, et non la classe d'objet sous-jacente faisant l'objet de la recherche ...
Martin Milan
Avez-vous des exemples de ceci, .Find () ou en surchargeant Object.Equals / GetHashCode?
Jan Johansen
@Martin IT serait très cassé si vous vouliez que la comparaison de deux CartProductobjets se comporte différemment à différents endroits.
Rowland Shaw
1
@Rowland - Mais je ne dis pas qu'il devrait changer le fonctionnement d'une comparaison. S'il veut un objet spécifique, utilisez Contains (). S'il veut un objet correspondant à un critère spécifié, utilisez Find () avec un prédicat approprié (expression lamda) ... Je soutiens en fait que vous ne touchez pas du tout au code de comparaison - vous appelez simplement la bonne méthode sur le liste pour la tâche que vous essayez d'accomplir ...
Martin Milan
1
@Martin Apparemment, j'ai mal interprété votre commentaire comme étant quelque chose du genre "override Contains()". D'accord, cela Find()pourrait résoudre le problème, bien que je suggère qu'une méthode d'égalité appropriée puisse être plus utile dans de nombreux autres cas, car le PO n'a pas remarqué que les références pour deux instances de la même entité étaient différentes.
Rowland Shaw
1

Vous devez créer un objet à partir de votre liste comme:

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

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

Cet objet obtient la valeur recherchée en recherchant ses propriétés: x.name

Ensuite, vous pouvez utiliser des méthodes de liste telles que Contains ou Remove

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

Mettre en œuvre override Equals()etGetHashCode()

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

}

utilisé:

if (CartProducts.Contains(p))
A. Morel
la source
-1

Si vous voulez en avoir le contrôle, vous devez implémenter l '[IEquatable interface] [1]

[1]: http: // Cette méthode détermine l'égalité en utilisant le comparateur d'égalité par défaut, tel que défini par l'implémentation de l'objet de la méthode IEquatable.Equals pour T (le type de valeurs dans la liste).

Gerrie Schenck
la source