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.

+3


source to share


1 answer


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.

+1


source







All Articles