SequenceEqual Operator in LINQ

SequenceEqual Operator in LINQ

In this article, I am going to discuss the SequenceEqual Operator in LINQ with some examples. Please read our previous article before proceeding to this article where we discussed the DefaultIfEmpty method in LINQ.

The SequenceEqual Operator in Linq is used to check whether two sequences are equal or not. If two sequences are equal then it returns true else it returns false.

Two sequences are considered to be equal when both the sequences have the same number of elements as well as the same values should be present in the same order.

There are two overloaded versions available for this SequenceEqual method as shown in the following image.

SequenceEqual Method in Linq

As you can see the second overloaded versions take an extra IEqualityComparer parameter.

Exampel1:

In the following example, we created two sequences to store the cities. As you can see both the collections contains the same number of elements. Further, if you notice all the elements are present in the same order in both the collection. So here the sequences are equal and the SequenceEqual method is going to return true.

using System.Linq;
using System;
using System.Collections.Generic;
namespace LINQDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            List<string> cityList1 = new List<string> { "Delhi", "Mumbai", "Hyderabad" };
            List<string> cityList2 = new List<string> { "Delhi", "Mumbai", "Hyderabad" };

            bool IsEqual = cityList1.SequenceEqual(cityList2);

            Console.WriteLine(IsEqual);

            Console.ReadLine();
        }
    }
}

Output: True

Example2: 

The default comparer the SequencesEqual method uses is case sensitive. So, in the below example, it returns false as the values are in case-sensitive.

using System.Linq;
using System;
using System.Collections.Generic;
namespace LINQDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            List<string> cityList1 = new List<string> { "DELHI", "mumbai", "Hyderabad" };
            List<string> cityList2 = new List<string> { "delhi", "MUMBAI", "Hyderabad" };

            bool IsEqual = cityList1.SequenceEqual(cityList2);

            Console.WriteLine(IsEqual);

            Console.ReadLine();
        }
    }
}

Output: False

Example3: 

If we want the comparison to be case-insensitive, then you need to use the other overloaded version of the SequenceEqual() method which takes IEqualityComparer as a parameter as shown in the below example.

using System.Linq;
using System;
using System.Collections.Generic;
namespace LINQDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            List<string> cityList1 = new List<string> { "DELHI", "mumbai", "Hyderabad" };
            List<string> cityList2 = new List<string> { "delhi", "MUMBAI", "Hyderabad" };

            bool IsEqual = cityList1.SequenceEqual(cityList2, StringComparer.OrdinalIgnoreCase);

            Console.WriteLine(IsEqual);

            Console.ReadLine();
        }
    }
}

Output: True

Note: If you go the definition of StringComparer class, then you will see that this class implements IEqualityComparer interface.

Example4: 

In the following example, the SequenceEqual method returns false. This is because the data are not present in the same order in both the sequences.

using System.Linq;
using System;
using System.Collections.Generic;
namespace LINQDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            List<string> cityList1 = new List<string> { "Delhi", "Mumbai", "Hyderabad" };
            List<string> cityList2 = new List<string> { "Delhi", "Hyderabad", "Mumbai" };

            bool IsEqual = cityList1.SequenceEqual(cityList2, StringComparer.OrdinalIgnoreCase);

            Console.WriteLine(IsEqual);
            Console.ReadLine();
        }
    }
}

Output: False

Example5:

If you want to solve the problem of the previous example, then first you need to sort the data and then apply the SequenceEqual method as shown in the below example.

using System.Linq;
using System;
using System.Collections.Generic;
namespace LINQDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            List<string> cityList1 = new List<string> { "Delhi", "Mumbai", "Hyderabad" };
            List<string> cityList2 = new List<string> { "Delhi", "Hyderabad", "Mumbai" };

            bool IsEqual = cityList1.OrderBy(city => city)
                    .SequenceEqual(cityList2.OrderBy(city => city), StringComparer.OrdinalIgnoreCase);

            Console.WriteLine(IsEqual);
            Console.ReadLine();
        }
    }
}

Output: True

Working with Complex Type:

We are going to work with the following Student class in this demo. So, create a class file with the name Student.cs and then copy and paste the following code in it.

using System.Collections.Generic;
namespace LINQDemo
{
    public class Student
    {
        public int ID { get; set; }
        public string Name { get; set; }

        public static List<Student> GetStudents1()
        {
            List<Student> listStudents = new List<Student>()
            {
                new Student{ID= 101,Name = "Preety"},
                new Student{ID= 102,Name = "Priyanka"}
            };
            return listStudents;
        }

        public static List<Student> GetStudents2()
        {
            List<Student> listStudents = new List<Student>()
            {
                new Student{ID= 101,Name = "Preety"},
                new Student{ID= 102,Name = "Priyanka"}
            };
            return listStudents;
        }
    }
}

Here in the above class, we created two methods i.e. GetStudents1 and GetStudents2. Further, if you notice these two methods are going to return the same data.

Please modify the Main method of the Program class as shown below.

using System.Linq;
using System;
using System.Collections.Generic;
namespace LINQDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Student> StudentList1 = Student.GetStudents1();
            List<Student> StudentList2 = Student.GetStudents2();

            bool IsEqual = StudentList1.SequenceEqual(StudentList2);

            Console.WriteLine(IsEqual);
            Console.ReadLine();
        }
    }
}

Output: False

Both the sequence contains the same data but here we are getting the output as False. This is because when comparing the complex types, the default comparer which is used by the SequenceEqual method will only check if the object references are equal or not.

How to solve the above problem?

There are many ways we can solve the above problem as follows.

  1. We need to use the other overloaded version of the SequenceEqual method to which we can pass a custom class that implements the IEqualityComparer interface.
  2. Project the properties into a new anonymous type, which overrides Equals() and GetHashCode() methods.
  3. In the Student class override the Equals() and GetHashCode() methods.
Creating Custom StudentComparer class:

Create a class file with the name StudentComparer.cs and then copy and paste the following code. As you can see this class implements the IEqualityComparer interface.

using System.Collections.Generic;
namespace LINQDemo
{
    public class StudentComparer : IEqualityComparer<Student>
    {
        public bool Equals(Student x, Student y)
        {
            return x.ID == y.ID && x.Name == y.Name;
        }

        public int GetHashCode(Student obj)
        {
            return obj.ID.GetHashCode() ^ obj.Name.GetHashCode();
        }
    }
}
Modifying the Main method:

Now in the Main method of the Program class, we need to create an instance of StudentComparer class and then we need to pass that instance to the SequenceEqual method as shown below.

using System.Linq;
using System;
using System.Collections.Generic;
namespace LINQDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Student> StudentList1 = Student.GetStudents1();
            List<Student> StudentList2 = Student.GetStudents2();

            StudentComparer studentComparer = new StudentComparer();
            bool IsEqual = StudentList1.SequenceEqual(StudentList2, studentComparer);

            Console.WriteLine(IsEqual);
            Console.ReadLine();
        }
    }
}

With the above changes, now run the application and it should return True.

Using Anonymous Type:

In the below example, we are projecting the data into an anonymous type.

using System.Linq;
using System;
using System.Collections.Generic;
namespace LINQDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Student> StudentList1 = Student.GetStudents1();
            List<Student> StudentList2 = Student.GetStudents2();

            var IsEqual = StudentList1
                    .Select(std => new { std.ID, std.Name })
                    .SequenceEqual(StudentList2.Select(std => new { std.ID, std.Name }));
            
            Console.WriteLine(IsEqual);
            Console.ReadLine();
        }
    }
}

Output: True

Overriding the Equals and GetHashCode method in Student Class:

Modify the Student class as shown below.

using System.Collections.Generic;
namespace LINQDemo
{
    public class Student
    {
        public int ID { get; set; }
        public string Name { get; set; }

        public static List<Student> GetStudents1()
        {
            List<Student> listStudents = new List<Student>()
            {
                new Student{ID= 101,Name = "Preety"},
                new Student{ID= 102,Name = "Priyanka"}
            };
            return listStudents;
        }

        public static List<Student> GetStudents2()
        {
            List<Student> listStudents = new List<Student>()
            {
                new Student{ID= 101,Name = "Preety"},
                new Student{ID= 102,Name = "Priyanka"}
            };
            return listStudents;
        }

        public override bool Equals(object x)
        {
            return this.ID == ((Student)x).ID && this.Name == ((Student)x).Name;
        }

        public override int GetHashCode()
        {
            return this.ID.GetHashCode() ^ this.Name.GetHashCode();
        }
    }
}

Now modify the Main method of the Program class as shown below.

using System.Linq;
using System;
using System.Collections.Generic;
namespace LINQDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Student> StudentList1 = Student.GetStudents1();
            List<Student> StudentList2 = Student.GetStudents2();

            var IsEqual = StudentList1.SequenceEqual(StudentList2);
            
            Console.WriteLine(IsEqual);
            Console.ReadLine();
        }
    }
}

Output: True

In the next article, I am going to discuss the Partitioning Operators in Linq. In this article, I try to explain the SequenceEqual operators with some examples. I hope you understood the need and use of SequenceEqual Operator in Linq.

Leave a Reply

Your email address will not be published. Required fields are marked *