.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))

しかし、それは同様のカート製品を無視し、それが何をチェックするのか知らないようです-ID?それともすべて?

前もって感謝します!:)

回答:


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は、IDがのIDと一致する製品の存在をチェックしますp。の後にブール式を置い=>てチェックを実行できます。

これには、LINQ-to-SQLクエリだけでなく、メモリ内クエリでもContains機能するという利点があります。


12

特定のオブジェクトがリストに含まれているかどうかを確認します。

リストのFindメソッドを使用した方がよい場合があります。

ここに例があります

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

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

それが役に立てば幸い

また、LinQも確認する必要があります。これはやり過ぎですが、それでも便利なツールです...


1
Linqはどのようにしてやり過ぎになるのでしょうか?
Mel Gerats

@MEL-なぜこの単純なものに対してクエリと型推論を混同するのですか?とはいえ、ラムダに慣れていない人には読みやすいかもしれません...
マーティンミラノ

+1わかりやすい例、他の場所での変更の影響を受けないオプションを示しています(つまり、Equals()メソッドが何らかの理由で変更された場合)
Rowland Shaw

4

デフォルトでは、参照タイプには参照の等価性があります(つまり、2つのインスタンスは、それらが同じオブジェクトである場合にのみ等価です)。

独自の等価性を実装するには、オーバーライドObject.Equals(およびObject.GetHashCode一致)する必要があります。(そして、等価==演算子を実装することは良い習慣です。)


1
なぜObject.Equalsをオーバーライドするのですか?私にとっては、それに応じて検索コードを修正する方が理にかなっており、検索されるオブジェクトの基になるクラスではありません...
Martin Milan

これの例、.Find()、またはObject.Equals / GetHashCodeのオーバーライドはありますか?
Jan Johansen

@Martin ITは、2つのCartProductオブジェクトの比較を異なる場所で異なる動作にしたい場合、非常に壊れます。
Rowland Shaw

1
@Rowland-しかし、比較のしくみを変える必要があると言っているわけではありません。特定のオブジェクトが必要な場合は、Contains()を使用します。指定した条件に一致するオブジェクトが必要な場合は、適切な述語(ラムダ式)を指定してFind()を使用します...実際には、比較コードにまったく触れないでください。あなたが達成しようとしているタスクのリスト...
マーティンミラノ

1
@Martinがあなたのコメントを「オーバーライドContains()」の線に沿ったものであると誤って解釈したようです。Find()OPは同じエンティティの2つのインスタンスの参照が異なることを認識しなかったので、適切なequalsメソッドを使用することは、他のケースのロードでより役立つ可能性があることをお勧めしますが、問題を解決できることに同意します。
Rowland Shaw

1

次のようにリストからオブジェクトを作成する必要があります。

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

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

そのオブジェクトは、プロパティによって検索されたように見える値を取得します:x.name

次に、ContainsやRemoveなどのListメソッドを使用できます。

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://このメソッドは、T(リスト内の値のタイプ)に対するIEquatable.Equalsメソッドのオブジェクトの実装によって定義されているデフォルトの等値比較子を使用して、等値を決定します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.