6

I'm trying to determine the differences between two collections.

private ObservableCollection<SomeObject> _objectList = null;
private ObservableCollection<SomeObject> _cachedObjectList = null;

SomeObject implements IEquatable<SomeObject>

I'm using the following to determine if my two collections have any differences:

this._objectList.ToList().OrderBy(x => x.Id).SequenceEqual(this._cachedObjectList.ToList().OrderBy(x => x.Id));
  • The _cachedObjectList collection will not change.
  • You are able to Add, Remove, Or Modify an object in the _objectList collection.

How can i return a new list that contains any newly added, deleted, or otherwise modified object from the two collections.

Any help would be greatly appreciated!

IEquatable Implementation for SomeObject:

public class SomeObject : IEquatable<SomeObject>
{
        public int GetHashCode(SomeObject object)
        {
            return base.GetHashCode();
        }

        public bool Equals(SomeObject other)
        {
            bool result = true;


            if (Object.ReferenceEquals(other, null))
            {
                result = false;
            }

            //Check whether the compared objects reference the same data.
            if (Object.ReferenceEquals(this, other))
            {
                result = true;
            }
            else
            {
                // if the reference isn't the same, we can check the properties for equality
                if (!this.Id.Equals(other.Id))
                {
                    result = false;
                }

                if (!this.OtherList.OrderBy(x => x.Id).ToList().SequenceEqual(other.OtherList.OrderBy(x => x.Id).ToList()))
                {
                    result = false;
                }
            }

            return result;
        }
    }
}

EDIT: I only want the changes, if the _objectList contains a modified object, based on the IEquatable.Equals() then I'd like it returned. Otherwise, return new objects or removed objects in the list.

Michael G
  • 6,695
  • 2
  • 41
  • 59

1 Answers1

7

You would find the differences with

var newAndChanged = _objectList.Except(_cachedObjectList);
var removedAndChanged = _cachedObjectList.Except(_objectList);
var changed = newAndChanged.Concat(removedAndChanged);
H H
  • 263,252
  • 30
  • 330
  • 514
  • 1
    Answer is good, the only thing I would add is to make sure the type of object that the list contains implements `IEquatable(Of T)`. That is of course assuming that it's a custom type. See the following [link](http://msdn.microsoft.com/en-us/library/bb300779.aspx). – Dylan Vester Nov 03 '11 at 22:19
  • For some reason the IEquatable Equals is never reached, any ideas? – Michael G Nov 03 '11 at 22:25
  • @Michael: You can do a lot of things wrong when implementing IEquatable. – H H Nov 03 '11 at 22:30
  • In this case Concat is better than Union, first one is O(n) second one is at least O(n log n). – Saeed Amiri Nov 03 '11 at 22:31
  • @Henk: I've updated the question with my implementation of IEquatable – Michael G Nov 03 '11 at 22:31
  • @Saeed: But that would give duplicates, no? – H H Nov 03 '11 at 22:34
  • @MichaelG - Your GetHashCode() does not match your Equals(). And that's bad. Could be the cause here. – H H Nov 03 '11 at 22:38
  • @Henk no In this case it doesn't get a duplicate. – Saeed Amiri Nov 03 '11 at 22:41
  • @Henk, You're right, i wasn't overriding GetHashCode. However, even overriding GetHashCode Equals is never called for the IEquatable implementation? – Michael G Nov 03 '11 at 22:42
  • @Saeed: You're right, I wasn't thinking. The list would contain the old and new versions of the changes, they're not dupes. – H H Nov 03 '11 at 22:45
  • @HenkHolterman, okay, Concat, Except, and Union do not call the IEquatable.Equals(). – Michael G Nov 03 '11 at 22:52
  • @MichaelG - You can't use the default base.GetHashCode(). Make it return Id and see if that helps. – H H Nov 03 '11 at 22:54
  • @HenkHolterman, using the Id's HashCode still does not help. IEquatable.Equals does not execute when using Except, or Contact, etc. – Michael G Nov 03 '11 at 23:00
  • 1
    @MichaelG just forget about the IEquatable and create a seperate class that implements `IEqualityComparer(Of T)`, there is an overload on `Except` that takes that. – Dylan Vester Nov 03 '11 at 23:03
  • Thanks, I went with the IEqualityComparer. I appreciate everyone's help. – Michael G Nov 03 '11 at 23:13
  • OK. Do note that your Equals() needs a little improving. I would suggest `return false;` to replace `result = false;` – H H Nov 03 '11 at 23:16