.Contains () trên danh sách các đối tượng lớp tùy chỉnh


95

Tôi đang cố gắng sử dụng .Contains()hàm trên danh sách các đối tượng tùy chỉnh

Đây là danh sách:

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

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

Vì vậy, tôi cố gắng tìm một sản phẩm giỏ hàng tương tự trong danh sách:

if (CartProducts.Contains(p))

Nhưng nó bỏ qua các sản phẩm giỏ hàng tương tự và tôi dường như không biết nó kiểm tra những gì - ID? hay tất cả?

Cảm ơn trước! :)

Câu trả lời:


119

Bạn cần triển khai IEquatablehoặc ghi đè Equals()GetHashCode()

Ví dụ:

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
nhưng ở đâu GetHashCode()?
zionpi

1
Bạn không cần triển khai GetHashCode (). Nó hoạt động mà không có nó.
user890332

141

Nếu bạn đang sử dụng .NET 3.5 hoặc mới hơn, bạn có thể sử dụng các phương thức mở rộng LINQ để đạt được kiểm tra "chứa" với Anyphương pháp mở rộng:

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

Điều này sẽ kiểm tra sự tồn tại của một sản phẩm trong CartProductsđó có ID khớp với ID của p. Bạn có thể đặt bất kỳ biểu thức boolean nào sau =>để thực hiện kiểm tra.

Điều này cũng có lợi ích khi làm việc cho các truy vấn LINQ-to-SQL cũng như các truy vấn trong bộ nhớ, Containsnhưng không.


12

Nó kiểm tra xem liệu đối tượng cụ thể có được chứa trong danh sách hay không.

Bạn có thể tốt hơn bằng cách sử dụng phương pháp Tìm trong danh sách.

Đây là một ví dụ

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

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

Hy vọng điều đó sẽ giúp

Bạn cũng nên xem LinQ - có lẽ quá mức cần thiết cho điều này, nhưng dù sao thì một công cụ hữu ích ...


1
Làm thế nào Linq có thể quá mức cần thiết?
Mel Gerats

@MEL - Tại sao lại bị lẫn lộn trong một truy vấn và nhập suy luận cho một thứ đơn giản thế này? Điều đó nói rằng, mặc dù nó có thể là dễ đọc hơn với ai đó không quen thuộc với lamdas ...
Martin Milan

+1 Ví dụ rõ ràng hay, hiển thị tùy chọn sẽ không bị ảnh hưởng bởi các thay đổi ở nơi khác (tức là nếu Equals()phương pháp bị thay đổi vì bất kỳ lý do gì)
Rowland Shaw

4

Theo mặc định, các kiểu tham chiếu có tham chiếu bình đẳng (tức là hai trường hợp chỉ bằng nhau nếu chúng là cùng một đối tượng).

Bạn cần ghi đè Object.Equals(và Object.GetHashCodeso khớp) để thực hiện bình đẳng của riêng bạn. (Và sau đó là thực tiễn tốt để thực hiện một ==toán tử bình đẳng ,.)


1
Tại sao lại ghi đè Object.Equals, điều này có thể gây ra hậu quả ở những nơi khác trong mã? Đối với tôi, sẽ có ý nghĩa hơn nếu sửa đổi mã tìm kiếm cho phù hợp, chứ không phải loại đối tượng cơ bản đang được tìm kiếm ...
Martin Milan

Bạn có biết một số ví dụ về điều này, .Find () hoặc ghi đè Object.Equals / GetHashCode không?
Jan Johansen

@Martin CNTT sẽ rất hỏng nếu bạn muốn so sánh hai CartProductđối tượng hoạt động khác nhau ở những nơi khác nhau.
Rowland Shaw

1
@Rowland - Nhưng tôi không nói rằng anh ấy sẽ phải thay đổi cách so sánh hoạt động. Nếu anh ta muốn một đối tượng cụ thể, hãy sử dụng Chứa (). Nếu anh ta muốn bất kỳ đối tượng nào phù hợp với một tiêu chí cụ thể, hãy sử dụng Find () với một vị từ phù hợp (biểu thức lamda) ... Tôi thực sự lập luận rằng bạn không chạm vào mã so sánh TẤT CẢ - bạn chỉ cần gọi phương thức phù hợp trên danh sách cho nhiệm vụ bạn đang cố gắng hoàn thành ...
Martin Milan

1
@Martin Có vẻ như tôi đã hiểu sai nhận xét của bạn thành một thứ gì đó dọc theo dòng "ghi đè Contains()". Đồng ý rằng Find()có thể giải quyết vấn đề, mặc dù tôi sẽ đề nghị có một phương pháp bằng phù hợp có thể hữu ích hơn trong vô số trường hợp khác, vì OP không phát hiện ra rằng các tham chiếu cho hai trường hợp của cùng một thực thể là khác nhau.
Rowland Shaw

1

Bạn cần tạo một đối tượng từ danh sách của mình như:

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

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

Đối tượng đó nhận giá trị đã tìm kiếm theo thuộc tính của chúng: x.name

Sau đó, bạn có thể sử dụng các phương pháp Danh sách như Chứa hoặc Xóa

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

0

Thực hiện override Equals()GetHashCode()

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

}

đã sử dụng:

if (CartProducts.Contains(p))

-1

Nếu bạn muốn kiểm soát điều này, bạn cần triển khai [giao diện IEquatable] [1]

[1]: http: // Phương thức này xác định bình đẳng bằng cách sử dụng trình so sánh bình đẳng mặc định, được xác định bằng cách triển khai đối tượng của phương thức IEquatable.Equals cho T (kiểu giá trị trong danh sách).

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.