1

My code

    query1 = select value1, value2 from dbo.animal where animalname="tiger";
    query2 = select value1, value2 from dbo.animal where animalname="lion";
    List<Animal> list1 = db.ExecuteStoreQuery<Animal>(query1).ToList();
    List<Animal> list2 = db.ExecuteStoreQuery<Animal>(query2).ToList();
    // list1.Count = 1 list1[0].value1 = "a" list1[0].value2 = "b"
    // list2.Count = 1 list2[0].value1 = "a" list2[0].value2 = "b"
    // Now I would like to compare list1 and list2 to see if they are equal
    var list3 = list1.Except(list2);
   //At this point list3 is containing both list1 and list2 and using var made it
 //GenericList not the same type of list as List1 and List2

I tried List list3 = list1.Except(list2) but I get compile error.

So the question is how do I find out if list1 is equal to list2? I was hoping list3 would be the differences between list1 and list2 and therefore if the lists are equal list3.count() should be 0.

The nice thing about my data is I believe data in from query1 and query should be both in order and result in only 1 record each.

DoodleKana
  • 2,106
  • 4
  • 27
  • 45

1 Answers1

1

First of all, checking if the results of Except are empty cannot answer the "are these two lists equal?" question. It answers the "does list2 contain all the elements of list1?", which is not the same, because list2 may contain additional elements.

The nice thing about my data is I believe data in from query1 and query should be both in order and result in only 1 record each.

You can compare two identically ordered lists for equality using SequenceEqual, like this:

bool areIdentical = list1.SequenceEqual(list2);

If the ordering is different, you can also force it to be the same with OrderBy:

bool areIdentical = list1
    .OrderBy(animal=>animal.Id)
    .SequenceEqual(list2.OrderBy(animal=>animal.Id));
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • That is good to know. So I used SequenceEqual and for some reason areIdentical is false when list1 and list2 have exact same animal object. Do I need to implement custom Equals method for Animal type for SequenceEqual to work? – DoodleKana May 30 '14 at 17:09
  • @DoodleKana Yes, custom `GetHashCode` and `Equals` need to be there in order for the `SequenceEqual` to work properly. A good news is that if `Animal` has an `Id`, you could implement both of these methods by forwarding them to `Id`. – Sergey Kalinichenko May 30 '14 at 17:11
  • Awesome, I implemented both Equals and GetHashCode. When implementing Equals did seem very redundant. I wonder if there is shortcut if you meant to compare all the fields. My code looks like public override bool Equals(Object obj){ Animal a = (Animal)obj; if(a.name==name)&&(a.height==height)&& so on etc (20 members) return true; } – DoodleKana May 30 '14 at 17:44
  • @DoodleKana The only shortcut I know is to use the database ID, if your `Animal` class has one. Otherwise, you're stuck with checking member-by-member equality. Of course you could drop the inner `if`, and go for `return (a.name==name)&&(a.height==height)&&...`, but this wouldn't shrink the code all that much. – Sergey Kalinichenko May 30 '14 at 17:53
  • Unfortunately my class does not have id. But I did take your advice on just using return with no if. For the GetHashCode I used return field1.GetHashCode()*17 + field2.GetHashCode() + etc. It seems to be working. Not sure if you have to list out every field. But sounds like if you are comparing them all you would have to use all fields. I multiplied the first field by 17 cuz I saw some example on stackoverflow someone using it as a primenumber. – DoodleKana May 30 '14 at 18:03
  • @DoodleKana As far as overriding `GetHashCode` goes, although it certainly does not hurt to use all the fields, you do not have to use them all. [Here is a good answer on implementing GetHashCode](http://stackoverflow.com/a/263416/335858) when your objects have multiple fields. – Sergey Kalinichenko May 30 '14 at 18:13