Correct way to connect multiple properties to collection of objects?
Let's say I have an object where the following 3 properties (others have been omitted) make up a "unique" plan object (if they are equal to the same values in another Plan object).
public class Plan
{
public int ID { get; set; }
public Plan Parent { get; set; }
public ID SomeOtherProperty { get; set; }
}
Here's my code Join
where I missed the anonymous method for operators Join
(I know this code won't work by default):
oldPlans
.Join(newPlans, o => o, n => n, (o, n) => new { Old = o, New = n })
.ForEach(e =>
{
...
});
I want to execute C # Join
on two sets of Plan objects. I understand that one way is to use an anonymous method on the connection properties by writing out these three properties.
But is there any other method? Can I override GetHashCode
? When I tried this it didn't seem to call it this method. I also tried to override Equals, but it didn't seem to trigger either. Should I override the ==
and operators !=
? Can I explicitly name .GetHashCode()
for the key selector fields (if I flipped it)?
Is it possible for this Join to check the equality of these two objects without complicating the key selectors? Thank.
Your code works great for me - tracking through the ReferenceSource ends up using the default ObjectEqualityComparer that calls Equals()
, so your idea is correct.
So it comes down to how you implement Equals
and GetHashCode
. You have to override both if you override them, and the MSDN states are :
WARNING: If you override the GetHashCode method, you must also override Equals and vice versa. If your overridden Equals method returns true when two objects are tested for equality, then your overridden GetHashCode method should return the same value for the two objects.
Note that your class ID
must also handle both of these methods correctly, as it must be used Plan
to check for equality and get a hash code.
This program worked for me and only prints the second entry from ID=2
(note that I did SomeOtherProperty
it int
for simplicity too, but this does not affect the approach or the code):
class Program
{
public class Plan
{
public int ID { get; set; }
public Plan Parent { get; set; }
public int SomeOtherProperty { get; set; }
// added to show we don't care about this
public string IgnoreMe { get; set; }
public Plan(int id, int other, Plan parent, string ignore)
{
this.ID = id;
this.SomeOtherProperty = other;
this.Parent = parent;
this.IgnoreMe = ignore;
}
public override bool Equals(object obj)
{
Plan other = (Plan)obj;
// just check the relevant properties
return this.ID == other.ID
&& this.SomeOtherProperty == other.SomeOtherProperty
&& this.Parent == other.Parent;
// .. or alternatively
//return (new { ID, SomeOtherProperty, Parent })
// .Equals(new { other.ID, other.SomeOtherProperty, other.Parent });
}
// nicked from http://stackoverflow.com/a/4630550/1901857
public override int GetHashCode()
{
return new { ID, SomeOtherProperty, Parent }.GetHashCode();
}
// just to help debug
public override string ToString()
{
return string.Format("[ID: {0}, Other:{1}, Parent:{2}]", ID, SomeOtherProperty, Parent);
}
}
static void Main(string[] args)
{
var parentPlans = new Plan[] {
new Plan(101, 2, null, "parent1"),
new Plan(102, 3, null, "parent2"),
new Plan(103, 4, null, "parent3"),
new Plan(104, 5, null, "parent4")
};
List<Plan> oldPlans = new List<Plan>(new Plan[] {
new Plan(1, 2, parentPlans[0], "old1"),
new Plan(2, 3, parentPlans[1], "old2"),
new Plan(3, 4, parentPlans[2], "old3"),
new Plan(4, 5, parentPlans[3], "old4")
});
List<Plan> newPlans = new List<Plan>(new Plan[] {
new Plan(11, 2, parentPlans[0], "new1"), // different ID
new Plan(2, 3, parentPlans[1], "new2"), // same
new Plan(3, 14, parentPlans[2], "new3"), // different other ID
new Plan(4, 5, parentPlans[2], "new4") // different parent
});
foreach (var e in
oldPlans.Join(newPlans, o => o, n => n, (o, n) => new { Old = o, New = n }))
{
Console.WriteLine(e.Old + " / " + e.New);
};
}
}
If you think that your implementation Equals
and GetHashCode
had to work, then please place them in the matter, perhaps they are not quite right.