5

Page というオブジェクトと、AssociatedAttributes というカスタム プロパティを持つ p というインスタンスがあります。私が次のことをした場合:

int numMatchingAttributes = p.AssociatedAttributes.Intersect( p.AssociatedAttributes ).Distinct( ).Count( ); 

p には 6 つの AssociatedAttributes がありますが、numMatchingAttributes は最終的に 0 になります。なぜ6に等しくないのですか?

AssociatedAttributesは Type List<Attribute>( Attributeis my own class, not System.Attribute) and AttributeimplementsIComparable<Attribute>です。implement を持っていませんでしたIEquatableか?

これはCompareToin Attribute の実装です:

public int CompareTo(Attribute other)
{
    return Id.CompareTo(other.Id);
}

IdタイプGuidです。

これは Page の AssociatedAttributes プロパティです。

public List<Attribute> AssociatedAttributes
        {
        get
            {
            List<Attribute> list = new List<Attribute>( );
            using (
                PredictiveRecommendor dbContext =
                    new PredictiveRecommendor()){
                if ( dbContext != null )
                    { 
                    IQueryable<Attribute> query = from a in dbContext.PageAttributes
                                                  where a.Page.Id.Equals(this.Id)
                                                  select a.Attribute;
                    list = query.ToList(); 


                    }
                }
            return list;
            }
        }

(dbContext は Telerik OpenAccess コンテキストです)

更新: これが最終的に機能したものです: In Page は次の方法です:

public int numberOfIntersectedAssociatedAttributes ( Page other )
        {
        using ( PredictiveRecommendor dbContext = new PredictiveRecommendor( ) )
            {
            IQueryable<Attribute> thisAssocAttributes = from a in dbContext.PageAttributes
                                                        where a.Page.Id.Equals( this.Id )
                                                        select a.Attribute;
            IQueryable<Attribute> otherAssocAttributes = from a in dbContext.PageAttributes
                                                         where a.Page.Id.Equals( other.Id )
                                                         select a.Attribute;
            IQueryable<Attribute> interSection = thisAssocAttributes.Intersect( otherAssocAttributes );

            return interSection.ToList( ).Count;
            }
        }

それは醜いですが、うまくいきます。

4

1 に答える 1

8

の次の実装を検討してくださいPage

public class Page
{
    public List<Attribute> AssociatedAttributes
    {
        get
        {
            return new List<Attribute>() { 
                new Attribute { Value = "a" }, 
                new Attribute { Value = "b" }, 
                new Attribute { Value = "c" }, 
            };
        }
    }
}

ここでは、プロパティが呼び出されるAssociatedAttributesたびに異なるリストを返しています。AssociatedAttributesさらに、リスト内の実際のアイテムは、プロパティが呼び出されるたびに構築されます。これは、まったく同じAttributeオブジェクトへの参照を返すだけではありません。(私が推測する) はorをAttributeオーバーライドしないため、デフォルトの実装を使用します。これは、同じオブジェクトを参照している場合にのみ、オブジェクトが等しいと見なします。2 つのリスト内のオブジェクトは同じオブジェクトを参照していないため、内部的に同じ値を持つ場合でも、それらのいずれも互いに等しくありません。EqualsGetHashCodeobject

Attribute実装するという事実IComparableは無関係です。

動作を変更するために実行できる可能性のあることがいくつかあります。

  1. プロパティ ゲッターで新しいオブジェクトを構築するのではなく、同じ実際のオブジェクトへの参照を返します。これはおそらく、プロパティのプライベート バッキング フィールドを持ち、オブジェクトを一度構築してから、同じリストへの参照を返すことを意味します。

  2. EqualsandGetHashCodeをオーバーライドしAttributeて、その参照ではなくその値に依存するようにします。規則では、値が変化するオブジェクトを扱うのGetHashCodeは難しいため、オブジェクトが不変の場合にのみこれを行うように指示されます。IEquatable 必要に応じて、これに加えて実装して、静的に型指定されたEqualsメソッドを提供できます。を実装する場合でも、それを有効にしたい場合は、オーバーライドすることが重要であることに注意してください。GetHashCodeIEquatable

  3. を実装する新しいオブジェクトを作成しますIEqualityComparer<Attribute>。これは、オブジェクト自体の実装Attribute以外の何かに基づいて等しいかどうかを比較する方法を知っている、外部のオブジェクトになります。そのようなタイプのインスタンスを と に提供します。(それぞれに、カスタム等値比較子のオーバーロードがあります。)EqualsGetHashCodeIntersectDistinct

于 2013-08-21T19:21:47.960 に答える