LINQ to Object Join operator and equality - c#

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?

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.

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

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

Related

Equals method throws NullReferenceException

I recently came about this problem. I have a base Stamp class. Then I made two inherited classes OwnedStamp and AuctionStamp. I overrided the Equals and GetHashCode method in Stamp class like this:
public override bool Equals(object obj)
{
if(obj == null || this.GetType().Equals(obj.GetType()))
{
return false;
}
else
{
Stamp stamp = obj as Stamp;
return this.Title == stamp.Title;
}
}
public override int GetHashCode()
{
return Title.GetHashCode();
}
I also have overloaded these operators in the same class:
public static bool operator ==(Stamp lhs, Stamp rhs)
{
return lhs.Equals(rhs);
}
public static bool operator !=(Stamp lhs, Stamp rhs)
{
return !lhs.Equals(rhs);
}
Then I have this scenario:
OwnedStamp checkStamp = check.GetStampByTitle(stampTitle);
if(checkStamp != null && checkStamp.Price <= toCompare.Price)
{
picked.Add(check);
}
The checkStamp is not null and it holds the correct informtaion I need, but when i check for the equality for null it throws me the exception. I have other lines with code where I check for equality between two stamps of any type. I have tried couple of different Equals method realizations. The problem consists. I have red that checking equality in base class even if we pass child class to the method shouldn't be a problem. Any help would be apreciated!

List equality of a custom class

I have a class A, which holds a string property and overwrites Equals for equality testing.
public class A
{
public string Prop { get; }
public A(string val)
{
Prop = val;
}
public override bool Equals(object obj)
{
return obj is A arg && (Prop == arg.Prop);
}
public override int GetHashCode()
{
return base.GetHashCode();
}
}
I also have a class B which has a List<A> as property:
public class B
{
public IReadOnlyList<A> Prop { get; }
public B(IReadOnlyList<A> val)
{
Prop = val;
}
public override bool Equals(object obj)
{
// ...
}
public override int GetHashCode()
{
return base.GetHashCode();
}
}
I wanna be able to compare to instances of B for equality and order.
How can I write the Equals method in B by not rewriting the same code I wrote in A?
Is there a way to reuse the A Equals?
Update: My first version assumed B is derived from A.
A.Equals:
If A is not sealed, obj is A ... can return a false positive if different types are compared. So the corrected version:
public override bool Equals(object obj)
{
return obj is A other
&& this.Prop == other.Prop
&& this.GetType() == other.GetType(); // not needed if A is sealed
}
A.GetHashCode:
base.GetHashCode will return different hash codes for different but equal instances, which is wrong. Derive the hashcode from self properties instead. If Prop acts like some ID, then simply return Prop.GetHashCode()
B.Equals:
public override bool Equals(object obj)
{
return obj is B other
&& this.Prop.SequenceEqual(other.Prop) // will re-use A.Equals
&& this.Prop.GetType() == other.Prop.GetType() // not needed if different IReadOnlyList types are ok
&& this.GetType() == other.GetType(); // not needed if B is sealed
}
B.GetHashCode:
You can aggregate the hash codes of A instances. Here I use a simple XOR but if the same items can often come in a different order you can come up with something more fancy.
return Prop.Aggregate(0, (h, i) => h ^ i.GetHashCode());
Implementing Equals for a list can be done by using the SequenceEquals method (from System.Linq namespace), which ensures that each item in one list equals the item at the same index in the other list.
One thing you might consider changing, however is your implementation of GetHashCode. This method should return the same number if two items are equal (though it's not guaranteed that two items with the same hash code are equal). Using base.GetHashCode() does not meet this requirement, since the base is object in this case; according to the documentation, "hash codes for reference types are computed by calling the Object.GetHashCode method of the base class, which computes a hash code based on an object's reference", so objects only return the same HashCode if they refer to the exact same object.
The HashCode should be based on the same properties used to determine equality, so in this case we want to use Prop.GetHashCode() for class A, and we want to aggregate the hashcode for all the items in Prop for class B.
Here's one way the classes could be refactored:
public class A : IEquatable<A>
{
public string Prop { get; }
public A(string val)
{
Prop = val;
}
public bool Equals(A other)
{
if (other == null) return false;
return Prop == other.Prop;
}
public override bool Equals(object obj)
{
return Equals(obj as A);
}
public override int GetHashCode()
{
return Prop.GetHashCode();
}
}
public class B : IEquatable<B>
{
public IReadOnlyList<A> Prop { get; }
public B(IReadOnlyList<A> val)
{
Prop = val;
}
public bool Equals(B other)
{
if (other == null) return false;
if (ReferenceEquals(this, other)) return true;
if (Prop == null) return other.Prop == null;
return other.Prop != null && Prop.SequenceEqual(other.Prop);
}
public override bool Equals(object obj)
{
return Equals(obj as B);
}
public override int GetHashCode()
{
return Prop?.Aggregate(17,
(current, item) => current * 17 + item?.GetHashCode() ?? 0)
?? 0;
}
}
Linq contains a useful method to compare collections: SequenceEqual
public override bool Equals(object obj)
{
if (!(obj is B other))
{
return false;
}
if (this.Prop == null || other.Prop == null)
{
return false;
}
return this.Prop.SequenceEqual(other.Prop);
}
Also, implement IEquatable<T> when you override Equals.
How about something like this:
public override bool Equals(object obj)
{
if(!(obj is B))
{
return false;
}
var b = obj as B;
if(b.Prop.Count != this.Prop.Count)
{
return false;
}
for(var i =0; i < Prop.Count; i++)
{
if (!Prop.ElementAt(i).Equals(b.Prop.ElementAt(i)))
{
return false;
}
}
return true;
}

How do I override GetHashCode() without any numbers as fields?

All of the resources showing how to override Equals(object) and GetHashCode() use numeric fields to implement the GetHashCode() method:
Implementing the Equals Method
What's the best strategy for Equals and GetHashCode?
Why is it important to override GetHashCode when Equals method is overridden?
However, in my class, I do not have any numeric fields. It is a node in a tree with a reference to its parent, children, and an interface as the data:
public class Node
{
private IInterface myInterface;
private Node parent;
private List<Node> children = new List<Node>();
public override bool Equals(object obj)
{
if (obj == null || GetType() != obj.GetType())
{
return false;
}
var node = (Node)obj;
return myInterface == node.myInterface;
}
public override int GetHashCode()
{
???
}
}
What should I set the hashcode with?
According to Equals implementation, two Nodes instances are equal if and only if their myInterface are equal:
public override bool Equals(object obj)
{
if (obj == null || GetType() != obj.GetType())
{
return false;
}
var node = (Node)obj;
// instances are equal if and only if myInterface's are equal
return myInterface == node.myInterface;
}
That's why myInterface is the only source for GetHashCode:
public override int GetHashCode()
{
return null == myInterface ? 0 : myInterface.GetHashCode();
}
P.S. (Edited, thanks to Kris Vandermotten) Often, it's a good practice to check for ReferenceEquals in the Equals implementation before comparing potentially time/resource consuming myInterfaces:
public override bool Equals(object obj) {
// Easy tests:
// 1. If "this" and "obj" are in fact just the same reference?
// 2. Since `Node` (or Equals) is not sealed, the safiest is to check types
if (object.ReferenceEquals(this, obj))
return true;
else if (null == obj || other.GetType() != GetType())
return false;
// Potentially time/resource cosuming (we don't know IInterface implementation)
return ((Node) obj).myInterface == myInterface;
}

Warning: Object defines operator == or operator != but does not override Object.Equals(object o)

I'm programming in C# Unity and have really annoying problem - I want to define special Pair class with following relations:
public class Pair<T1>{
public int First;
public T1 Second;
public bool Equals(Pair<T1> b){
return First == b.First;
}
public static bool operator==(Pair<T1> a, Pair<T1> b){
return a.First == b.First;
}
public static bool operator!=(Pair<T1> a, Pair<T1> b){
return a.First != b.First;
}
}
Which gives me following warning:
Warning CS0660: 'Pair' defines operator == or operator != but does
not override Object.Equals(object o) (CS0660) (Assembly-CSharp)
But also when I spawn two objects of Pair type with same First integer, their == operator returns True (as I want). When I only declare Equals function, same == operator returns False value (I understand that somehow Unity compares their addressees in memory), with no warnings. Is there any method to avoid warnings and still get True value of == operator?
Just override that method to make the compiler happy :
public override bool Equals(object o)
{
if(o == null)
return false;
var second = o as Pair<T1>;
return second != null && First == second.First;
}
public override int GetHashCode()
{
return First;
}
The method you created is a custom equals method, you need to override that of the object class (which is used in the == && != operators)
You need to override the Equal:
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((Pair<T1>) obj);
}
And the GetHashCode method:
public override int GetHashCode()
{
unchecked
{
return (First*397) ^ EqualityComparer<T1>.Default.GetHashCode(Second);
}
}

Is this a good/efficient idiom for implementing Equals and equality/inequality operators?

I have had a few problems getting this right, so I wanted to ask if anyone has any feedback on whether this is an efficient way to implement the Equals method and equality/inequality operators for a custom immutable class. These operators are called very frequently by my program, so I want to make sure I get them right.
class MyObj
{
public static bool operator ==(MyObj a, MyObj b)
{
if (!object.ReferenceEquals(a, null))
return a.Equals(b);
else if (!object.ReferenceEquals(b, null))
return b.Equals(a);
else
// both are null
return true;
}
public static bool operator !=(MyObj a, MyObj b)
{
if (!object.ReferenceEquals(a, null))
return !a.Equals(b);
else if (!object.ReferenceEquals(b, null))
return !b.Equals(a);
else
// both are null
return false
}
public override bool Equals(object obj)
{
return this.Equals(obj as MyObj);
}
public bool Equals(MyObj obj)
{
if (object.ReferenceEquals(obj, null))
return false;
else
return (obj.FieldOne == this.FieldOne &&
obj.FieldTwo == this.FieldTwo && ...);
}
}
I use the following code snippet for reference types, which has less duplication and feels cleaner, in my opinion. Having a static "Equals" method allows .NET languages without operator overloading to compare your instances without having to test for null before calling the instance method. If you're implementing equality operators, it might also be best to make your class immutable, if you can.
class Foo : IEquatable<Foo>
{
public override bool Equals(object obj)
{
return Equals(obj as Foo);
}
public bool Equals(Foo other)
{
if (object.ReferenceEquals(other, null)) return false;
// Optional early out
if (object.ReferenceEquals(this, other)) return true;
// Compare fields here
}
public static bool Equals(Foo a, Foo b)
{
if (ReferenceEquals(a, null)) return ReferenceEquals(b, null);
return a.Equals(b);
}
public static bool operator ==(Foo a, Foo b)
{
return Equals(a, b);
}
public static bool operator !=(Foo a, Foo b)
{
return !Equals(a, b);
}
}
Some things I'm noticing:
Because you're overriding Equals, you should also override GetHashCode.
Since your Equals(MyObj) method is a valid implementation for the entire IEquatable<MyObj> interface, MyObj should indeed implement that interface. This will also allow Dictionary<> and such to directly take advantage of your Equals(MyObj) method, instead of going through Equals(object).
Also I completely agree with Trillian's alternative implementation, except I would've implemented a != b directly as !(a == b) instead of !Equals(a, b). (Trivial difference of course.)
Basically yes, but there is an error to correct.
The Equals(object) method calls itself instead of calling the Equals(MyObj) method, causing an eternal loop. It should be:
public override bool Equals(object obj) {
MyObj other = obj as MyObj;
return this.Equals(other);
}
or simply:
public override bool Equals(object obj) {
return this.Equals(obj as MyObj);
}
Also, you can simplify the inequality operator to:
public static bool operator !=(MyObj a, MyObj b) {
return !(a == b);
}
If you're looking for efficiency, I recommend using this instead of object.ReferenceEquals(foo, null):
(object)foo == null
This is effectively equivalent but avoids a function call.
I also like to implement IEquatable<T> in all my types that override Equals. For reference types, I then forward Equals(object) to Equals(Foo).
public override bool Equals(object other){return Equals(other as Foo);}
The operator overloads can be simplified as so:
public static bool operator==(Foo a, Foo b){
if((object)a == null)
return (object)b == null;
return a.Equals(b);
}
public static bool operator!=(Foo a, Foo b){
return !(a == b);
}
If absolute efficiency is needed, though, it may be worth a little duplication of code in these functions to avoid the extra function calls, but unlike using (object)foo == null instead of object.ReferenceEquals(foo, null), avoiding the function call requires extra code to maintain, so the small gain may not be worth it.
I prefer to leave all the "if this is null then do that else..." logic to the framework:
class MyObj : IEquatable<MyObj> {
public static bool operator ==( MyObj left, MyObj right ) {
return EqualityComparer<MyObj>.Default.Equals( left, right );
}
public static bool operator !=( MyObj left, MyObj right ) {
return !EqualityComparer<MyObj>.Default.Equals( left, right );
}
public override bool Equals( object obj ) {
return this.Equals( obj as MyObj );
}
public bool Equals( MyObj other ) {
return !object.ReferenceEquals( other, null )
&& obj.FieldOne == this.FieldOne
&& obj.FieldTwo == this.FieldTwo
&& ...
;
}
...
}
See also What is the best algorithm for an overridden GetHashCode? for implementing GetHashCode.

Categories