.Contains () в списке настраиваемых объектов класса

95

Я пытаюсь использовать .Contains()функцию в списке настраиваемых объектов

Это список:

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

Поэтому я пытаюсь найти похожий товар в тележке в списке:

if (CartProducts.Contains(p))

Но он игнорирует похожие товары на тележке, и я, кажется, не знаю, что он проверяет - идентификатор? или все это?

Заранее спасибо! :)

Ян Йохансен
источник

Ответы:

119

Вам необходимо реализовать IEquatableили переопределить Equals()иGetHashCode()

Например:

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
а где это GetHashCode()?
zionpi
1
Вам не нужно реализовывать GetHashCode (). Работает и без него.
user890332
141

Если вы используете .NET 3.5 или новее, вы можете использовать методы расширения LINQ для проверки «содержит» с помощью Anyметода расширения:

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

Это проверит наличие продукта, в CartProductsкотором есть идентификатор, соответствующий идентификатору p. Вы можете поместить любое логическое выражение после, =>чтобы выполнить проверку.

Это также дает преимущество работы с запросами LINQ-to-SQL, а также с запросами в памяти, где Containsнет.

Пол Тернер
источник
12

Он проверяет, содержится ли конкретный объект в списке.

Возможно, вам лучше использовать метод поиска в списке.

Вот пример

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

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

надеюсь, это поможет

Вам также стоит взглянуть на LinQ - возможно, излишний, но, тем не менее, полезный инструмент ...

Мартин Милан
источник
1
как Linq может быть излишним?
Мел Гератс,
@MEL - Зачем путаться в запросе и выводе типа для чего-то такого простого? Тем не менее, это может быть более читаемым для тех, кто не знаком с ламдами ...
Мартин Милан,
+1 Хороший ясный пример, который показывает вариант, на который не повлияли бы изменения где-либо еще (то есть, если бы Equals()метод был изменен по какой-либо причине)
Роуленд Шоу,
4

По умолчанию ссылочные типы имеют ссылочное равенство (т.е. два экземпляра равны, только если они являются одним и тем же объектом).

Вам нужно переопределить Object.EqualsObject.GetHashCodeсопоставить), чтобы реализовать собственное равенство. (И тогда рекомендуется реализовать оператор равенства ==,,.)

Ричард
источник
1
Зачем переопределять Object.Equals, что может иметь последствия в другом месте кода? Для меня имеет больше смысла вносить соответствующие поправки в поисковый код, а не на базовый класс объекта, по которому выполняется поиск ...
Мартин Милан,
У вас есть примеры этого, .Find () или переопределение Object.Equals / GetHashCode?
Ян Йохансен,
@Martin IT был бы очень нарушен, если бы вы хотели, чтобы сравнение двух CartProductобъектов в разных местах велось по-разному.
Роуленд Шоу,
1
@Rowland - Но я не говорю, что ему придется изменить принцип работы сравнения. Если ему нужен конкретный объект, используйте Contains (). Если ему нужен какой-либо объект, соответствующий заданным критериям, используйте Find () с подходящим предикатом (lamda-выражение) ... Я на самом деле утверждаю, что вы не трогаете код сравнения ВООБЩЕ - вы просто вызываете правильный метод на список для задачи, которую вы пытаетесь выполнить ...
Мартин Милан,
1
@Martin Похоже, я неверно истолковал ваш комментарий как что-то вроде «переопределения Contains()». Согласитесь, что это Find()могло бы решить проблему, хотя я бы посоветовал иметь подходящий метод equals может быть более полезным во множестве других случаев, поскольку OP не обнаружил, что ссылки для двух экземпляров одной и той же сущности были разными.
Rowland Shaw,
1

Вам нужно создать объект из вашего списка, например:

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

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

Этот объект получает искомое значение при поиске по их свойствам: x.name

Затем вы можете использовать методы списка, такие как Contains или Remove

if (lst.Contains(obj))
{
   lst.Remove(obj);
}
Хосе Чавес
источник
0

Реализовать 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();
        }

}

используемый:

if (CartProducts.Contains(p))
А. Морель
источник
-1

Если вы хотите контролировать это, вам необходимо реализовать [интерфейс IEquatable] [1]

[1]: http: // Этот метод определяет равенство с помощью компаратора равенства по умолчанию, как это определено реализацией объекта метода IEquatable.Equals для T (тип значений в списке).

Герри Шенк
источник