IKnow IEquatable

Well, now anyway. Sometimes I think the statement “Necessity is the mother of invention.” should – when applied to coders – be restated as “Necessity is the mother of fruitless hacks, StackOverflow searches and more code.” Catchy, eh?

Prior to my somewhat painful re-education (not going to use a diaeresis this time), I was operating under the ridiculous assumption that comparing to collections would be straightforward…if not downright simple. But my code kept telling me two identical collections were not. Of course a better coder would immediately recognize a reference problem underlying this. First I had blithely tried:

if (savedExercisesCollection != ExercisesCollection)
{
 for (int i = 0; i < ExercisesCollection.Count; i++)
 {
 ExercisesCollection[i].Order = i;
 }

App.StorageSettings["SettingsChanged"] = true;
}

But that was always returning true. Next, I turned to LINQ (’cause it is the solver of all problems, isn’t it?). Well, at any rate, my thinking was that it would actually compare the values. And it is elegantly concise:

if (savedExercisesCollection.Except(ExercisesCollection).Any())
{
 for (int i = 0; i < ExercisesCollection.Count; i++)
 {
 ExercisesCollection[i].Order = i;
 }</pre>
App.StorageSettings["SettingsChanged"] = true;
 }

I had also tried SequenceEqual but with the same sad results…until I stumbled across the IEqualityComparer<T> IEquatable @ http://msdn.microsoft.com/en-us/library/bb348567.aspx.

if (!savedExercisesCollection.SequenceEqual(ExercisesCollection))
{
 for (int i = 0; i < ExercisesCollection.Count; i++)
 {
 ExercisesCollection[i].Order = i;
 }

App.StorageSettings["SettingsChanged"] = true;
}

Now I was on the path to righteousness. All it would take is adding a comparer to my original class. I approached this with some trepidation since I’m relying on being able to serialize portions of that class. But the only way to know if something will blow up is to light the fuse. Turns out no worries.

I modified the class as follows:

[DataContract]
 public class Exercise : IEquatable<Exercise>
 {
 public List<Asset> AssetsList;

public Exercise(int id, int order, string description)
 {
 Id = id;

Order = order;

Description = description;

AssetsList = new List<Asset>();
 }

[DataMember]
 public int Id { get; set; }

[DataMember]
 public int Order { get; set; }

[DataMember]
 public string Description { get; set; }

 public bool Equals(Exercise other)
 {
 //Check whether the compared object is null.
 if (ReferenceEquals(other, null)) return false;

//Check whether the compared object references the same data.
 if (ReferenceEquals(this, other)) return true;

//Check whether the products' properties are equal.
 return Id.Equals(other.Id) && Order.Equals(other.Order);
 }

The take-home lesson from this is that unless an ObservableCollection is instantiated from the same source as another they are not automatically comparable. I can see this knowledge coming in handy when rehydrating a chunk of JSON, for instance to compare a remotely stored to-do list with one on the client.