the_drow
the_drow

Reputation: 19171

LINQ to Object Join operator and equality

I have the following simple LINQ to Object query:

var accountsWithOpportunities = (from a in accountGetServices
                                 join o in opportunities on a equals o.Account
                                 select a).ToList();

This query always 0 results but this query does not:

var accountsWithOpportunities = (from a in accountGetServices
                                 join o in opportunities on a.Id equals o.Account.Id
                                 select a).ToList();

Therefor, I reached to the conclusion that my equality operation is doing something wrong. I have the following abstract class that is being used for all models:

public abstract class BaseModel<T> : BaseModel
        where T : class, IIdentifyable
    {
        public static bool operator ==(BaseModel<T> c1, BaseModel<T> c2)
        {
            T t1 = c1 as T;
            T t2 = c2 as T;

            if (object.ReferenceEquals(t1, t2)) return true;
            if (object.ReferenceEquals(t1, null)) return false;
            if (object.ReferenceEquals(t2, null)) return false;

            return c1.Equals(c2);
        }

        public static bool operator !=(BaseModel<T> c1, BaseModel<T> c2)
        {
            return !(c1 == c2);
        }
    }

    public abstract class BaseModel : IEquatable<BaseModel>
    {
        public bool Equals(BaseModel other)
        {
            if (other == null)
                return false;

            var identifyable1 = this as IIdentifyable;
            var identifyable2 = other as IIdentifyable;

            return identifyable1.Id == identifyable2.Id;
        }

        public override bool Equals(object obj)
        {
            return base.Equals(obj) && Equals(obj as BaseModel);
        }
    }

I placed breakpoints on each function to see what goes on under the hood but none of them are hit.
What am I doing wrong?

Upvotes: 2

Views: 629

Answers (3)

Dave
Dave

Reputation: 462

public override bool Equals(object obj)
{
  return base.Equals(obj) && Equals(obj as BaseModel);
}

This part seems to be wrong. base.Equals calls object.ReferenceEquals which always (or at least in most of the cases) returns false and therefore the other expression is never evaluated.

EDIT

Also, as you pointed out earlier, GetHashCode gets called (you should get a compiler warning that you've overridden Equals but not GetHashCode). So change the GetHashCode to return the Id of the entity and it should start working.

Upvotes: 2

the_drow
the_drow

Reputation: 19171

The real solution is to override GetHashCode() to always return 0. Then all the equality functions are being hit.
I'm not sure why or if there's a better way to implement GetHashCode().

Upvotes: 0

Klaus Byskov Pedersen
Klaus Byskov Pedersen

Reputation: 120917

Is public override bool Equals(object obj) not being hit? I see you are calling object.Equals here which would make it always return false. A better implementation would be:

public override bool Equals(object obj)
{
    return this.Equals(obj as BaseModel);
}

Upvotes: 0

Related Questions