The LINQ Query operators are a series of continuation methods that form a query pattern. These functions are the extension methods for either IEnumerable<T> and IQueryable<T> and they’re defined in the System.Linq.Queryable and System.Linq.Enumerable predefined libraries,
They form the building blocks of LINQ query expressions and are called by using either static method syntax or instance method syntax.
There are around 50 standard query operators available in LINQ that include set operations, concatenation, sorting operators, filtering operators, element operators, aggregation, and so on. The set operations include four methods: Distinct, Except, Intersect, and Union.
What Is LINQ Distinct Method in C#?
C# Linq Distinct() method removes the duplicate elements from a sequence (list) and returns the distinct elements from a single data source. It comes under the Set operators’ category in LINQ query operators, and the method works the same way as the DISTINCT directive in Structured Query Language (SQL).
Syntax of Linq Distinct Method in C#:
IEnumerable<data type> result = numbers.Distinct();
Here is a sample code showing the implementation of C# LINQ Distinct().
using System;
using System.Linq;
using System.Collections.Generic;
namespace Ctutorials
{
class Linqprogram
{
static void Main(string[ ] args)
{
String[ ] fruits = { "Apple", "Banana", "Apple", "Plum", "Grapes", "Plum" };
IEnumerable<string> result= fruits.Distinct(); //LINQ distinct function
foreach (var item in result)
{
Console.WriteLine(item);
}
Console.ReadLine();
}
}
}
Output
APPLE
BANANA
PLUM
GRAPES
Explanation
The array read multiple strings, and the LINQ distinct removed the repeated elements in the list.
Examples of LINQ Distinct Method Using Both Method and Query Syntax
Here’s an example code that will read students’ marks with C# LINQ Distinct Method using both Method and Query Syntax.
using System;
using System.Collections.Generic;
using System.Linq;
namespace LINQCode
{
class GradeMarks
{
static void Main(string[] args)
{
List<int> intCollection = new List<int>()
{
90,67,78,89,98,89,90,87,78,82,90,78
};
//Method Syntax
var Marks = intCollection.Distinct();
//Query Syntax
var Grades = (from num in intCollection select num).Distinct();
foreach (var item in Marks)
{
Console.WriteLine(item);
}
Console.ReadKey();
}
}
}
Output
90
67
78
89
98
87
82
How to Implement IEqualityComparer?
By default, LINQ distinct() in C# is case-sensitive. So, the default equality comparer might work well for numbers, but you might not get the exact distinct list in strings.
To solve this, we use the IEqualityComparer.
Syntax: public abstract class StringComparer: IComparer, IEqualityComparer, IComparer <string>,
What if we change the case of the first fruit program we discussed? Doing so will display the entire list since the C# LINQ distinct function is case-sensitive. Let’s see how we can make it work by using the IEqualityComparer.
using System;
using System.Linq;
using System.Collections.Generic;
namespace Ctutorials
{
class Linqprogram
{
static void Main(string[] args)
{
string[] fruits = { "Apple", "Banana", "apple", "Plum", "Grapes", "plum" };
//Using IEqualityComparer
IEnumerable<string> result= fruits.Distinct(StringComparer.OrdinalIgnoreCase);
foreach (var item in result)
{
Console.WriteLine(item);
}
Console.ReadLine();
}
}
}
Output
APPLE
BANANA
PLUM
GRAPES
LINQ Distinct Operation With Complex Type
Now, what if we add the name of students to the marks obtained by them above?
Lets understand it through a code sample.
create a file named StudentMarks.cs to store the complex list.
using System;
using System.Linq;
using System.Collections.Generic;
namespace LINQTutorial
{
public class StudentMarks
{
public int Marks { get; set; }
public string Name { get; set; }
public static List<Student> GetStudents()
{
List<Student> students = new List<Student>()
{
new Student {Marks = 90, Name = "Vaibhav" },
new Student {Marks = 67, Name = "Akash" },
new Student {Marks = 78, Name = "Anjali" },
new Student {Marks = 89, Name = "Rithik" },
new Student {Marks = 98, Name = "Harsh" },
new Student {Marks = 89, Name = "Anjali" },
new Student {Marks = 90, Name = "Akash" },
new Student {Marks = 87, Name = "Sameera" },
new Student {Marks = 78, Name = "Priya" },
new Student {Marks = 82, Name = "Harsh" },
new Student {Marks = 90, Name = "Vaibhav" },
new Student {Marks = 78, Name = "Anjali" },
};
return students;
}
}
}
We will use this code in the main method.
using System;
using System.Linq;
namespace LINQTutorial
{
class MainStudent
{
public static void Main(string[] args)
{
//Using Method Syntax
var MS = Student.GetStudents()
.Select(std => std.Name)
.Distinct().ToList();
//Using Query Syntax
var QS = (from std in Student.GetStudents(select std.Name)
.Distinct().ToList();
foreach(var item in MS)
{
Console.WriteLine(item);
}
Console.ReadKey();
}
}
}
By default, The C# LINQ Distinct function will only be able to sort by either removing repeating student names or repeating marks.
How to Solve the Problem?
This problem can be solved by two different approaches.
- Overriding the Equals() and GetHashCode() methods within the Student class
- Using IEquatable<T> interface
Method 1
Create a file named StudentMarks.cs to type this code.
using System.Collections.Generic;
namespace LINQTutorial
{
public class StudentMarks
{
public int ID { get; set; }
public string Name { get; set; }
public static List<Student> GetStudents()
{
List<Student> students = new List<Student>()
{
new Student {Marks = 90, Name = "Vaibhav" },
new Student {Marks = 67, Name = "Akash" },
new Student {Marks = 78, Name = "Anjali" },
new Student {Marks = 89, Name = "Rithik" },
new Student {Marks = 98, Name = "Harsh" },
new Student {Marks = 89, Name = "Anjali" },
new Student {Marks = 90, Name = "Akash" },
new Student {Marks = 87, Name = "Sameera" },
new Student {Marks = 78, Name = "Priya" },
new Student {Marks = 82, Name = "Harsh" },
new Student {Marks = 90, Name = "Vaibhav" },
new Student {Marks = 78, Name = "Anjali" },
};
return students;
}
public override bool Equals(object obj)
{
//typecasting obj to Student Type
return this.ID == ((Student)obj).ID && this.Name == ((Student)obj).Name;
}
public override int GetHashCode()
{
//Getting the ID hash code value
int IDHashCode = this.ID.GetHashCode();
//Getting the string HashCode Value
int NameHashCode = this.Name == null ? 0 : this.Name.GetHashCode();
return IDHashCode ^ NameHashCode;
}
}
}
Now, we will call the method in the main function through this code:
using System;
using System.Linq;
namespace LINQTutorial
{
class MainStudent
{
public static void Main(string[] args)
{
// Method Syntax
var MS = Student.GetStudents()
.Distinct().ToList();
// Query Syntax
var QS = (from std in Student.GetStudents()
select std)
.Distinct().ToList();
foreach (var item in MS)
{
Console.WriteLine($"ID : {item.ID} , Name : {item.Name} ");
}
Console.ReadKey();
}
}
}
Output
Marks = 90, Name = Vaibhav
Marks = 67, Name = Akash
Marks = 78, Name = Anjali
Marks = 89, Name = Rithik
Marks = 98, Name = Harsh
Marks = 87, Name = Sameera
Method 2
Write this code sample in a new file named StudentMarks.cs.
using System.Collections.Generic;
namespace LINQTutorial
{
public class StudentMarks : IEquatable<StudentMarks>
{
public int ID { get; set; }
public string Name { get; set; }
public static List<StudentMarks> GetStudentsMarks()
{
List<StudentMarks> StudentMarkstudents = new List<StudentMarks>()
{
new Student {Marks = 90, Name = "Vaibhav" },
new Student {Marks = 67, Name = "Akash" },
new Student {Marks = 78, Name = "Anjali" },
new Student {Marks = 89, Name = "Rithik" },
new Student {Marks = 98, Name = "Harsh" },
new Student {Marks = 89, Name = "Anjali" },
new Student {Marks = 90, Name = "Akash" },
new Student {Marks = 87, Name = "Sameera" },
new Student {Marks = 78, Name = "Priya" },
new Student {Marks = 82, Name = "Harsh" },
new Student {Marks = 90, Name = "Vaibhav" },
new Student {Marks = 78, Name = "Anjali" },
};
return students;
}
public bool Equals(StudentMarks other)
{
if (object.ReferenceEquals(other, null))
{
return false;
}
if (object.ReferenceEquals(this, other))
{
return true;
}
return this.ID.Equals(other.ID) && this.Name.Equals(other.Name);
}
//creating the hashcode function
public override int GetHashCode()
{
int IDHashCode = this.ID.GetHashCode();
int NameHashCode = this.Name == null ? 0 : this.Name.GetHashCode();
return IDHashCode ^ NameHashCode;
}
}
}
Now, paste this code in the main method.
using System;
using System.Linq;
namespace LINQTutorial
{
class MainStudent
{
static void Main(string[] args)
{
//Method Syntax
var MS = StudentMarks.GetStudentsMarks()
.Distinct().ToList();
//Query Syntax
var QS = (from std in StudentMarks.GetStudents()
select std)
.Distinct().ToList();
foreach (var item in MS)
{
Console.WriteLine($"ID : {item.ID} , Name : {item.Name} ");
}
Console.ReadKey();
}
}
}
Output
Marks = 90, Name = Vaibhav
Marks = 67, Name = Akash
Marks = 78, Name = Anjali
Marks = 89, Name = Rithik
Marks = 98, Name = Harsh
Marks = 87, Name = Sameera
Conclusion
Now that you have a strong understanding of C# linq distinct, you should learn the other important aspects and concepts of the language with this tutorial. However, in order to become a proficient full stack developer, knowledge of just one language may not be enough. You can enrol in our world-class Post Graduate Program in Full Stack Web Development and scale your programming and development career to new heights. Explore and enrol now!
If you have any questions regarding the article or the course, feel free to post them in the comments below. Our experts will review them and get back to you at the earliest.