5

我有一个名为 Page 的对象,有一个名为 p 的实例,它有一个名为 AssociatedAttributes 的自定义属性。如果我执行以下操作:

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

numMatchingAttributes 最终等于 0,即使 p 有 6 个 AssociatedAttributes。为什么不等于6?

AssociatedAttributes是类型List<Attribute>Attribute是我自己的类,不是System.Attribute)和Attribute实现IComparable<Attribute>,我没有实现IEquatable,应该吗?

这是CompareTo属性中的实现:

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 上下文)

更新:这是最终的工作:在页面中是以下方法:

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对象的引用。由于Attribute(我假设)不会覆盖Equalsor GetHashCode,它将使用默认object实现,当且仅当它们引用同一个对象时,它才认为对象相等。由于两个列表中的对象没有引用相同的对象,因此它们都不相等,即使它们在内部可能具有相同的值。

Attribute实施的事实IComparable是无关紧要的。

有几种可能的事情可以改变行为:

  1. 与其在属性 getter 中构造新对象,不如返回对相同实际对象的引用。这可能意味着拥有一个私有的属性支持字段,构造一次对象,然后返回对同一个列表的引用。

  2. 覆盖Equals并依赖于它的值,而不是它的引用GetHashCodeAttribute约定将规定您仅在对象不可变时才这样做,因为处理具有变异GetHashCode值的对象是......困难的。IEquatable 如果您愿意,除了执行此操作之外,您还可以实现提供静态类型的Equals方法。请注意,如果您仍然希望它有用,则重写它是至关重要的GetHashCodeIEquatable

  3. 创建一个实现IEqualityComparer<Attribute>. 这将是一个外部对象,Attribute它知道如何根据对象本身的实现Equals和实现以​​外的其他内容来比较它们是否相等。向和GetHashCode提供这种类型的实例。(它们每个都有自定义相等比较器的重载。)IntersectDistinct

于 2013-08-21T19:21:47.960 回答