-2

I am using two lists. Both of them have exactly the same properties and namings. Is it possible to check the both lists are equal or not?

public class Person
 {
     public string Name { get; set; }
     public int Age { get; set; }
     public Person(string name, int age)
     {
         this.Name = name;
         this.Age = age;
     }
 }


 var list1 = new List<Person>();
 list1.Add(new Person("Dim", 12));
 list1.Add(new Person("Dio", 13));

 var list2 = new List<Person>();
 list2.Add(new Person("Dim", 12));
 list2.Add(new Person("Dio", 13));

 bool listsEqual = list1 == list2;

 Debug.WriteLine("Lists are equal: " + listsEqual);
DmO
  • 357
  • 2
  • 14
  • Your `Person` class does not override the `Equals` method and `==` only checks reference-equality, you want to call `object.Equals` or `Equals` on your list – knittl Aug 10 '23 at 07:05
  • 1
    Check this: https://stackoverflow.com/questions/12795882/quickest-way-to-compare-two-generic-lists-for-differences – Rafael Aug 10 '23 at 07:07
  • Is it good way to serialize them? var equal = JsonSerializer.Serialize(list1) == JsonSerializer.Serialize(list2); – DmO Aug 10 '23 at 07:08
  • @DmO no, it's orders of magnitude slower and uses infinitely more memory (equality doesn't use memory, serialization uses a lot). What you ask for is already available through [SequenceEquals](https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.sequenceequal?view=net-7.0) – Panagiotis Kanavos Aug 10 '23 at 07:10
  • Thank you Panagiotis. var equal = list1.SequenceEqual(list2); returns not equal – DmO Aug 10 '23 at 07:12
  • 2
    Yes, because ... where's the equality comparer for `Person`? You get `false` if you compare two Person instances with the same values because the default comparer for *classes* only uses reference equality. Not so with records or structs. You can provide a custom comparer to `SequenceEquals` though – Panagiotis Kanavos Aug 10 '23 at 07:13
  • Equality in the dot net world is kind of confusing when it comes to reference types. Basically, equality of references can mean one of two different things - the first is reference equality (meaning both references points to the same instance in memory) and the other is value-based equality (meaning both references might point to different instances in memory, but the values these instances represent are equal - in your case, the the name and age properties have the same values). – Zohar Peled Aug 10 '23 at 07:16
  • I read the documentation, and i wondering, we are using c# 11 and there is not just a single line code for comparing two lists. We need to implement extra code. – DmO Aug 10 '23 at 07:16
  • [`IEnumerable.SequenceEquals`](https://stackoverflow.com/questions/10511130/difference-between-equals-and-sequenceequal) is a single method call, what extra do you need to implement? (apart from the `Equals` method in your `Person` class, how else would C# know when 2 instances are equal?) – knittl Aug 10 '23 at 07:18
  • @knittl You need two implement each property one by one. If in future decide to add two more properties you need to remember adding them `public bool Equals(Person other) { if (other is null) return false; return this.Name == other.Name && this.Age == other.Age; }` – DmO Aug 10 '23 at 07:20
  • @DmO if you don't want that, use `record` instead of `class`. `public record Person(string name,int Age);`. You get immutability and automatically generated Equals, GetHashCode and ToString implementations. For class types, all IDEs can generate Equals and GetHashCode automatically. `if in the future` you type `Ctrl + .` in Visual Studio or Rider and select `Implement Equals` from the list of refactorings. – Panagiotis Kanavos Aug 10 '23 at 07:39

2 Answers2

3

You need to use IEquatable Interface for this.

public class Person : IEquatable<Person>
 {
     public string Name { get; set; }
     public int Age { get; set; }
     public Person(string name, int age)
     {
         this.Name = name;
         this.Age = age;
     }
    public bool Equals(Person other)
    {
        if (other is null)
            return false;

        return this.Name == other.Name && this.Age == other.Age;
    }

    public override bool Equals(object obj) => Equals(obj as Person);
    public override int GetHashCode() => (Name, Age).GetHashCode();
 }

Then you can use SequenceEqual() method from System.Linq

var list1 = new List<Person>();
         list1.Add(new Person("Dim", 12));
         list1.Add(new Person("Dio", 13));

         var list2 = new List<Person>();
         list2.Add(new Person("Dim", 12));
         list2.Add(new Person("Dio", 13));
 
        bool test = list1.SequenceEqual(list2);
        Console.WriteLine(test);
HarrY
  • 607
  • 4
  • 14
1

In C#, when you use the == operator to compare two lists, it will check if the two lists reference the same object in memory, not if their contents are the same.

use the SequenceEqual method from the System.Linq namespace.

https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.sequenceequal?view=net-7.0

  • To use `SequenceEqual` there must be an equality comparer for `Person` AND the list must be sorted (same order of elements). – Poul Bak Aug 10 '23 at 07:18
  • @PoulBak nothing was said about order. The question asked how to compare two lists for equality. Not check if they have the same elements. Besides, both SequenceEqual and any methods that check for differences accept custom comparers – Panagiotis Kanavos Aug 10 '23 at 07:20
  • @PanagiotisKanavos: Ok, I phrased it badly. I meant that it will return false if it contains the same elements in a different order. – Poul Bak Aug 10 '23 at 07:25