0% found this document useful (0 votes)
49 views

Part - 13 LINQ Intersect Method

The LINQ Intersect method returns common elements between two collections. There are two overloaded versions - one for value types and one that takes an IEqualityComparer for complex types. When using Intersect with complex types like classes, the default comparer checks only reference equality. Examples show using a custom StudentComparer class implementing IEqualityComparer to compare properties for complex type intersection.
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
49 views

Part - 13 LINQ Intersect Method

The LINQ Intersect method returns common elements between two collections. There are two overloaded versions - one for value types and one that takes an IEqualityComparer for complex types. When using Intersect with complex types like classes, the default comparer checks only reference equality. Examples show using a custom StudentComparer class implementing IEqualityComparer to compare properties for complex type intersection.
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 10

LINQ Intersect Method

The LINQ Intersect Method in C# is used to return the common elements from both collections. The
elements that are present in both data sources are going to be returned by Intersect Method. There
are two overloaded versions available for the Intersect Method in C#. They are as follows.

The one and only difference between the above two LINQ Intersect methods is that the second
overloaded version takes IEqualityComparer as an argument. That means when we are working with
Complex Types, in order to work as expected, we can use the overloaded method which takes the
IEqualityComparer parameter.

Examples to Understand LINQ Intersect Method using C#


Let us understand LINQ Intersect Method with an example. Please have a look at the below image.
As you can see in the below image, here we have two integer data sources i.e. DataSource 1 and
Data Source 2. DataSource 1 contains elements such as 1, 2, 3, 4, 5, and 6, and DataSource 2
contains elements such as 1, 3, 5, 8, 9, and 10. If we want to retrieve the elements such as 1, 3, and
5 which exist in both the data sources then we need to use the LINQ Intersect method.

LINQ Intersect Method Example using Method and Query Syntax:


The following example shows the use of the LINQ Intersect() Method using both Method and Query
Syntax to fetch the common elements that exist in both collections. In query syntax, there is no such
operator called Intersect, so here we need to use the mixed syntax i.e. both the query and method
syntax to achieve the same.
using System.Collections.Generic;
using System;
using System.Linq;
namespace LINQDemo
{
class Program
{
static void Main(string[] args)
{
List<int> dataSource1 = new List<int>() { 1, 2, 3, 4, 5, 6 };
List<int> dataSource2 = new List<int>() { 1, 3, 5, 8, 9, 10 };

//Method Syntax
var MS = dataSource1.Intersect(dataSource2).ToList();

//Query Syntax
var QS = (from num in dataSource1
select num)
.Intersect(dataSource2).ToList();

foreach (var item in MS)


{
Console.WriteLine(item);
}

Console.ReadKey();
}
}
}

LINQ Intersect() Method Example with String Array using C#:


Let us see the examples to understand how the Intersect Method works with string collection. Here, in
the below example, we have two arrays of countries and our requirement is to return the common
countries i.e. the countries which exist in both collections.
using System;
using System.Linq;
namespace LINQDemo
{
class Program
{
static void Main(string[] args)
{
string[] dataSource1 = { "India", "USA", "UK", "Canada", "Srilanka" };
string[] dataSource2 = { "India", "uk", "Canada", "France", "Japan" };

//Method Syntax
var MS = dataSource1.Intersect(dataSource2).ToList();

//Query Syntax
var QS = (from country in dataSource1
select country)
.Intersect(dataSource2).ToList();

foreach (var item in QS)


{
Console.WriteLine(item);
}

Console.ReadKey();
}
}
}
Now run the application and you should get the output as expected as shown in the below image.

As you can see it displays only India and Canada. If you look at our collections, then you can see the
country “UK” is present in both collections but the Intersect method did not fetch that country. This is
because the default comparer that is being used by the Intersect method is case-insensitive.

So if you want to ignore the case-sensitive then you need to use the other overloaded version of the
Intersect() method which takes IEqualityComparer as an argument. So, modify the program as shown
below where we pass StringComparer as an argument to the Intersect() method which will ignore the
case sensitivity while comparing the values.
using System;
using System.Linq;
namespace LINQDemo
{
class Program
{
static void Main(string[] args)
{
string[] dataSource1 = { "India", "USA", "UK", "Canada", "Srilanka" };
string[] dataSource2 = { "India", "uk", "Canada", "France", "Japan" };

//Method Syntax
var MS = dataSource1.Intersect(dataSource2,
StringComparer.OrdinalIgnoreCase).ToList();

//Query Syntax
var QS = (from country in dataSource1
select country)
.Intersect(dataSource2, StringComparer.OrdinalIgnoreCase).ToList();

foreach (var item in QS)


{
Console.WriteLine(item);
}

Console.ReadKey();
}
}
}
Now run the application and it will display the data as expected as shown in the below image.

LINQ Intersect Method with Complex Type in C#:


The LINQ Intersect() Method like other Set Methods (such as Distinct, Expect) also works in a
different manner when working with complex data types such as Product, Employee, Student, etc. Let
us understand this with an example. Create a class file with the name Student.cs and then copy and
paste the following code into it.
namespace LINQDemo
{
public class Student
{
public int ID { get; set; }
public string Name { get; set; }
}
}
This is a very simple student class with just two properties. Let’s say, we have the following two data
sources.
As you can see in the above image, we have two collections of student data. And if you notice we
have two students which are appeared in both collections. Our requirement is to fetch all the student
names which are present in both collections. That is the common student’s names from both
collections. To achieve the same, modify the Main method of the Program class as follows. In the
below example, from the first data source, we are fetching the student names by using the select
method and then we use the Intersect method and then we fetching the student names from the
second data source.
using System.Collections.Generic;
using System;
using System.Linq;
namespace LINQDemo
{
class Program
{
static void Main(string[] args)
{
List<Student> StudentCollection1 = new List<Student>()
{
new Student {ID = 101, Name = "Preety" },
new Student {ID = 102, Name = "Sambit" },
new Student {ID = 105, Name = "Hina"},
new Student {ID = 106, Name = "Anurag"},
};

List<Student> StudentCollection2 = new List<Student>()


{
new Student {ID = 105, Name = "Hina"},
new Student {ID = 106, Name = "Anurag"},
new Student {ID = 107, Name = "Pranaya"},
new Student {ID = 108, Name = "Santosh"},
};

//Method Syntax
var MS = StudentCollection1.Select(x => x.Name)
.Intersect(StudentCollection2.Select(y => y.Name)).ToList();

//Query Syntax
var QS = (from std in StudentCollection1
select std.Name)
.Intersect(StudentCollection2.Select(y => y.Name)).ToList();

foreach (var name in MS)


{
Console.WriteLine(name);
}

Console.ReadKey();
}
}
}
When you run the above code, you will get the output as expected as shown in the below image:

More Complex Examples to Understand LINQ Intersect Example:


Now our requirement is to select all the information of all the students who are present in both
collections. In order to do this, let us modify the program class as shown below.
using System.Collections.Generic;
using System;
using System.Linq;
namespace LINQDemo
{
class Program
{
static void Main(string[] args)
{
List<Student> StudentCollection1 = new List<Student>()
{
new Student {ID = 101, Name = "Preety" },
new Student {ID = 102, Name = "Sambit" },
new Student {ID = 105, Name = "Hina"},
new Student {ID = 106, Name = "Anurag"},
};

List<Student> StudentCollection2 = new List<Student>()


{
new Student {ID = 105, Name = "Hina"},
new Student {ID = 106, Name = "Anurag"},
new Student {ID = 107, Name = "Pranaya"},
new Student {ID = 108, Name = "Santosh"},
};

//Method Syntax
var MS = StudentCollection1.Intersect(StudentCollection2).ToList();

//Query Syntax
var QS = (from std in StudentCollection1
select std).Intersect(StudentCollection2).ToList();

foreach (var student in MS)


{
Console.WriteLine($" ID : {student.ID} Name : {student.Name}");
}

Console.ReadKey();
}
}
}
Once you run the application, then it will not display any data. This is because the default comparer
which is used by the LINQ Intersect Method for comparison is only checked whether two object
references are equal and not the individual property values of the complex object. And in this case,
each student object has a different reference and hence it is not returning any student data. As we
already discussed we can overcome this problem in many different ways. Let us understand each way
one by one.

Using IEqualityComparer Comparer with LINQ Intersect Method in C#:


In this approach, we need to create a class and then we need to implement
the IEqualityComparer interface and we need to provide the implementation for the Equals and
GetHashCode method. So, create a class file with the name StudentComparer.cs and then copy and
paste the following code into it.
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();
}
}
}
Next, we need to create an instance of StudentComparer class and then we need to pass that
instance to the Intersect method. So, modify the Main method of the Program class as follows.
using System.Collections.Generic;
using System;
using System.Linq;
namespace LINQDemo
{
class Program
{
static void Main(string[] args)
{
List<Student> StudentCollection1 = new List<Student>()
{
new Student {ID = 101, Name = "Preety" },
new Student {ID = 102, Name = "Sambit" },
new Student {ID = 105, Name = "Hina"},
new Student {ID = 106, Name = "Anurag"},
};

List<Student> StudentCollection2 = new List<Student>()


{
new Student {ID = 105, Name = "Hina"},
new Student {ID = 106, Name = "Anurag"},
new Student {ID = 107, Name = "Pranaya"},
new Student {ID = 108, Name = "Santosh"},
};

StudentComparer studentComparer = new StudentComparer();

//Method Syntax
var MS = StudentCollection1
.Intersect(StudentCollection2, studentComparer).ToList();

//Query Syntax
var QS = (from std in StudentCollection1
select std)
.Intersect(StudentCollection2, studentComparer).ToList();

foreach (var student in QS)


{
Console.WriteLine($" ID : {student.ID} Name : {student.Name}");
}

Console.ReadKey();
}
}
}
With the above changes in place, run the application and you will get the output as expected as
shown in the below image.

Using Anonymous Type for Intersect Operation in C#:


In this approach, we need to select all the individual properties to an anonymous type using the LINQ
select operator or Select Extension Method. The following program does exactly the same thing.
using System.Collections.Generic;
using System;
using System.Linq;
namespace LINQDemo
{
class Program
{
static void Main(string[] args)
{
List<Student> StudentCollection1 = new List<Student>()
{
new Student {ID = 101, Name = "Preety" },
new Student {ID = 102, Name = "Sambit" },
new Student {ID = 105, Name = "Hina"},
new Student {ID = 106, Name = "Anurag"},
};

List<Student> StudentCollection2 = new List<Student>()


{
new Student {ID = 105, Name = "Hina"},
new Student {ID = 106, Name = "Anurag"},
new Student {ID = 107, Name = "Pranaya"},
new Student {ID = 108, Name = "Santosh"},
};

//Method Syntax
var MS = StudentCollection1.Select(x => new { x.ID, x.Name })
.Intersect(StudentCollection2.Select(x => new { x.ID, x.Name })).ToList();

//Query Syntax
var QS = (from std in StudentCollection1
select new { std.ID, std.Name })
.Intersect(StudentCollection2.Select(x => new { x.ID, x.Name })).ToList();
foreach (var student in MS)
{
Console.WriteLine($" ID : {student.ID} Name : {student.Name}");
}

Console.ReadKey();
}
}
}
With the above changes in place, now run the application code again and you will get the output as
expected as shown in the below image.

Overriding Equals() and GetHashCode() Methods within the Student Class


This is the third approach and in this approach we need to override the Equals and GetHashCode() in
the Student class. As we know, by default, any type (predefined or user-defined) .NET Framework is
inherited from the Object class. That means the Student class is also inherited from the Object class.
So, we can override the Equals() and GetHashCode() methods of the Object class within the Student
class. So, modify the Student class as shown below. Here, we are overriding the Equals() and
GetHashCode() methods.
namespace LINQDemo
{
public class Student
{
public int ID { get; set; }
public string Name { get; set; }

public override bool Equals(object obj)


{
//As the obj parameter type is object, so we need to
//cast it to Student Type
return this.ID == ((Student)obj).ID && this.Name == ((Student)obj).Name;
}

public override int GetHashCode()


{
//Get the ID hash code value
int IDHashCode = this.ID.GetHashCode();
//Get the string HashCode Value
//Check for null refernece exception
int NameHashCode = this.Name == null ? 0 : this.Name.GetHashCode();
return IDHashCode ^ NameHashCode;
}
}
}
Next, modify the Main method of the Program class as shown below. Here, we need to use the
overloaded version of the Intersect method which does not take any parameter.
using System.Collections.Generic;
using System;
using System.Linq;
namespace LINQDemo
{
class Program
{
static void Main(string[] args)
{
List<Student> StudentCollection1 = new List<Student>()
{
new Student {ID = 101, Name = "Preety" },
new Student {ID = 102, Name = "Sambit" },
new Student {ID = 105, Name = "Hina"},
new Student {ID = 106, Name = "Anurag"},
};

List<Student> StudentCollection2 = new List<Student>()


{
new Student {ID = 105, Name = "Hina"},
new Student {ID = 106, Name = "Anurag"},
new Student {ID = 107, Name = "Pranaya"},
new Student {ID = 108, Name = "Santosh"},
};

//Method Syntax
var MS = StudentCollection1.Intersect(StudentCollection2).ToList();

//Query Syntax
var QS = (from std in StudentCollection1
select std).Intersect(StudentCollection2).ToList();

foreach (var student in MS)


{
Console.WriteLine($" ID : {student.ID} Name : {student.Name}");
}

Console.ReadKey();
}
}
}
Now run the application and again, you will get the same output as the previous two examples as
shown in the below image.

Implementing IEquatble<T> Interface in Student Class.


This is the last approach and, in this approach, we need to implement the IEquatble<T> Interface in
Student Class and we need to implement the Equals Method of the IEquatble<T> Interface and we
also need to override the GetHashCode method of the Object class. So, modify the Student class as
shown below.
using System;
namespace LINQDemo
{
public class Student : IEquatable<Student>
{
public int ID { get; set; }
public string Name { get; set; }

public bool Equals(Student other)


{
return this.ID.Equals(other.ID) && this.Name.Equals(other.Name);
}
public override int GetHashCode()
{
int IDHashCode = this.ID.GetHashCode();
int NameHashCode = this.Name == null ? 0 : this.Name.GetHashCode();
return IDHashCode ^ NameHashCode;
}
}
}
As you can see, here we have done two things. First, we implement the Equals method of the
IEquatable interface and then we override the GetHashCode method of the Object class. With the
above changes in place, now modify the Main Method of the Program class as shown below.
using System.Collections.Generic;
using System;
using System.Linq;
namespace LINQDemo
{
class Program
{
static void Main(string[] args)
{
List<Student> StudentCollection1 = new List<Student>()
{
new Student {ID = 101, Name = "Preety" },
new Student {ID = 102, Name = "Sambit" },
new Student {ID = 105, Name = "Hina"},
new Student {ID = 106, Name = "Anurag"},
};

List<Student> StudentCollection2 = new List<Student>()


{
new Student {ID = 105, Name = "Hina"},
new Student {ID = 106, Name = "Anurag"},
new Student {ID = 107, Name = "Pranaya"},
new Student {ID = 108, Name = "Santosh"},
};

//Method Syntax
var MS = StudentCollection1.Intersect(StudentCollection2).ToList();

//Query Syntax
var QS = (from std in StudentCollection1
select std).Intersect(StudentCollection2).ToList();

foreach (var student in MS)


{
Console.WriteLine($" ID : {student.ID} Name : {student.Name}");
}

Console.ReadKey();
}
}
}
Now, run the application and you will also get the same output as expected.

You might also like