In this article, I am going to discuss the LINQ Distinct Method in C# using examples. Please read our previous article where we discussed the basics of LINQ Set Operators. At the end of this article, you will understand the following the Linq Distinct Query in details with the following pointers.
- What is LINQ Distinct Method in C#?
- Examples of LINQ Distinct Method using both Method and Query Syntax
- How to implement IEqualityComparer?
What us LINQ Distinct Method in C#?
The LINQ Distinct Method in C# is used to return the distinct elements from a single data source. There are two overloaded versions available for the Distinct Method as shown below.
The one and the only difference between these two methods is the second overloaded version takes an IEqualityComparer as input that means the Distinct Operator can also be used with Comparer also. If this is not clear at the moment, dont worry we will cover the use of the Comparer in this Video also.
Example1: LINQ Distinct Method on Value Type
Here we have an integer collection that contains duplicate integer values. Our requirement is to fetch remove the duplicate values and return only the distinct values as shown below.
The following program shows how to get the distinct integer values using both Method and Query syntax:
Output:
Note: In query syntax, there is no such operator call distinct, so here we need to use both query and method syntax to achieve the same.
Example2:
Here we have a string array of names and we need to return the distinct names from the collection.
When we execute the above program, it gives us the below output.
As you can see the name Hina and Abc have appeared twice. This is because the default comparer, which is used to filter the duplicate values is case-sensitive.
If you want to make the comparison to be case-insensitive then you need to use the other overloaded version which takes IEqualityComparer as an argument. So here we need to pass a class which must implement the IEqualityComparer interface.
So lets modify the program as shown below. As you can see here we are passing StringComparer as an argument to the Distinct method.
Now run the application and it should display the distinct names as shown below.
If we go to the definition of StringComparer class then we can observe that this class implements the IEqualityComparer interface as shown below.
LINQ Distinct Operation with Complex Type:
The LINQ Distinct Method works in a different manner with complex types like Employee, Product, Student, etc. Let us understand with an example. We are going to work with the following Student data.
Create a class file with the name Student.cs and then copy and paste the following code.
Here we created the student class with the required properties. Along the same way, we have GetStudents() method which will return all the students.
Example3:
Here we need to fetch all the distinct names from the students collection. The following programs show how to achieve this using both Method and Query syntax.
Output:
Example4:
Now we need to select distinct students from the collection. As you can see in our collection three students are identical and in our result set, they should appear only once. Let us modify the program class as shown below.
Now execute the query and see the output.
As you can see, it will not select distinct students rather it select all the students. This is because the default comparer which is used for comparison is only checked whether two object references are equal and not the individual property values of the complex object.
How to solve the above problem?
We can solve the above problem in four different ways. They are as follows
- We need to use the other overloaded version of Distinct() method which takes IEqualityComparer interface as an argument. So here we will create a class that implements IEqualityComparer interface and then we need to pass that compare instance to the Distinct() method.
- In the second approach, we need to override the Equals() and GetHashCode() methods within the Student class itself.
- In the third approach, we need to project the required properties into a new anonymous type, which already overrides the Equals() and GetHashCode() methods
- By Implementing IEquatable<T> interface.
Approach2: Implementing IEqualityComparer interface
Create a class file with the name StudentComparer.cs and then implement the IEqualityComparer interface as shown below.
As you can here we implements the IEqualityComparer<T> interface and then implements the Equals() and GetHashCode() methods. Now we need to create an instance of StudentComparer class and then we need to pass that instance to the Distinct method as shown in the below program.
Now run the application and it will display the distinct students as shown below.
Approach2: Overriding the Equals() and GetHashCode() methods
Now, we need to override the Equals() and GetHashCode() methods within the Student class. So, modify the Student class as shown below.
With the above changes in Student class, modify the Main method as shown below.
Now execute the program and it will display the distinct records as expected.
Approach3: Using Anonymous Type
Here we need to project the properties of Student class into a new anonymous type, which already overrides the Equals() and GetHashCode() methods.
In the above example, we project the ID and Name properties to IEnumeable<a> means to anonymous type which already overrides the Equals and GetHashCode method. Now run the application and you will see the output as expected.
Approach4: Implementing the IEquatble<T> interface in Student Class.
Modify the Student class as shown below.
As you can see, here we have done two things. First, we implement the Equals method of the IEquatable interface and then override the GetHashCode method.
Now change the Program class as shown below.
Run the application and see the output as expected.
Difference between IEqualityComparer<T> and IEquatable<T>:
The IEqualityComparer<T> is an interface for an object that performs the comparison on two objects of the type T whereas the IEquatable<T> is also an interface for an object of type T so that it can compare itself to another.