Özel sınıf nesneleri listesinde içerir ()


95

.Contains()İşlevi özel nesneler listesinde kullanmaya çalışıyorum

Bu liste:

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

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

Bu yüzden listede benzer bir sepet ürünü bulmaya çalışıyorum:

if (CartProducts.Contains(p))

Ama benzer araba ürünlerini görmezden geliyor ve neyi kontrol ettiğini bilmiyorum - kimlik? yoksa hepsi mi?

Şimdiden teşekkürler! :)

Yanıtlar:


119

Uygulamanız IEquatableveya geçersiz kılmanız Equals()veGetHashCode()

Örneğin:

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

4
ama nerede GetHashCode()?
zionpi

1
GetHashCode () uygulamanıza gerek yoktur. Onsuz çalışır.
user890332

141

.NET 3.5 veya daha yenisini kullanıyorsanız, Anyuzantı yöntemiyle "içerir" denetimi gerçekleştirmek için LINQ uzantı yöntemlerini kullanabilirsiniz :

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

Bu, CartProductskimliği ile eşleşen bir kimliği olan bir ürünün varlığını kontrol edecektir p. =>Kontrolü gerçekleştirmek için herhangi bir boole ifadesini öğesinden sonra koyabilirsiniz .

Bu aynı zamanda LINQ'dan SQL'e sorgular ve bellek içi sorgular için çalışma avantajına da sahiptir Contains.


12

Listede belirli bir nesnenin bulunup bulunmadığını kontrol eder.

Listedeki Bul yöntemini kullanmanız daha iyi olabilir.

İşte bir örnek

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

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

umarım yardımcı olur

Ayrıca LinQ'ya da bakmalısınız - bunun için abartılı olabilir, ancak yine de kullanışlı bir araç ...


1
Linq nasıl aşırı olabilir?
Mel Gerats

@MEL - Neden bir sorguya karışıp bu kadar basit bir şey için çıkarım yazasınız? Bununla birlikte, lamdalara aşina olmayan biri için daha okunabilir olduğunu söyledi ...
Martin Milan

+1 Başka bir yerdeki değişikliklerden etkilenmeyecek seçeneği gösteren iyi ve açık bir örnek (yani Equals()yöntem herhangi bir nedenle değiştirilirse)
Rowland Shaw

4

Varsayılan olarak referans türlerinin referans eşitliği vardır (yani, iki örnek yalnızca aynı nesneyse eşittir).

Kendi eşitliğinizi uygulamak için geçersiz kılmanız Object.Equals(ve Object.GetHashCodeeşleşmeniz) gerekir. (Ve bu durumda bir eşitlik ==operatörü uygulamak iyi bir uygulamadır .)


1
Kodun başka yerlerinde sonuçları olabilecek Object.Equals neden geçersiz kılınır? Bana göre, arama kodunu buna göre değiştirmek daha mantıklı geliyor, aranan nesnenin temelini oluşturan sınıf değil ...
Martin Milan

Bunun, .Find () veya Object.Equals / GetHashCode'u geçersiz kılma örnekleri var mı?
Jan Johansen

@Martin BT, iki CartProductnesnenin karşılaştırmasının farklı yerlerde farklı davranmasını istiyorsanız çok bozulur .
Rowland Shaw

1
@Rowland - Ama karşılaştırmanın çalışma şeklini değiştirmesi gerektiğini söylemiyorum. Belirli bir nesne istiyorsa, İçerir () kullanın. Belirli bir kriterle eşleşen herhangi bir nesneyi istiyorsa, uygun bir yüklemle (lamda ifadesi) Find () kullanın ... Aslında karşılaştırma koduna HER ŞEYDE dokunmadığınızı iddia ediyorum - sadece doğru yöntemi Başarmaya çalıştığınız görevin listesi ...
Martin Milan

1
@Martin Görünüyor Yorumunuzu "geçersiz kılma Contains()" satırlarında bir şey olarak yanlış yorumladım . Find()OP, aynı varlığın iki örneğinin referanslarının farklı olduğunu fark etmediğinden, uygun bir eşittir yöntemine sahip olmanın diğer birçok durumda daha yararlı olabileceğini önermeme rağmen, sorunu çözebileceğini kabul edin .
Rowland Shaw

1

Listenizden aşağıdaki gibi bir nesne oluşturmanız gerekir:

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

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

Bu nesne, özelliklerine göre aranan bakılan değeri alır: x.name

Ardından İçerir veya Kaldır gibi Liste yöntemlerini kullanabilirsiniz.

if (lst.Contains(obj))
{
   lst.Remove(obj);
}

0

Uygulayın override Equals()veGetHashCode()

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

}

Kullanılmış:

if (CartProducts.Contains(p))

-1

Bunun üzerinde kontrol sahibi olmak istiyorsanız [IEquatable arayüzü] [1] uygulamanız gerekir

[1]: http: // Bu yöntem, nesnenin T için IEquatable.Equals yönteminin (listedeki değerlerin türü) uygulaması tarafından tanımlanan varsayılan eşitlik karşılaştırıcısını kullanarak eşitliği belirler.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.