Loading

Microsoft .Net 6 LINQ

How to handle LINQ Except in C# ?. The Complete Microsoft .Net 6 LINQ Developer Course 2023 [Videos].

In this article, I am going to discuss the LINQ Except in C# with examples. Please read our previous article where we discussed the LINQ Distinct Method with examples. As part of this article, we are going to discuss the following pointers

  1. What is LINQ Except in C#?
  2. Examples of C# LINQ Except Method using both Method and Query Syntax
  3. How to implement IEqualityComparer?
  4. Example using Anonymous Type
What is LINQ Except in C#?

The LINQ Except Method in C# is used to return the elements which are present in the first data source but not in the second data source. There are two overloaded versions available for the LINQ Except Method as shown below.

LINQ Except Method in C# with Examples

The one and the only difference between the above two methods is the second overloaded version takes IEqualityComparer as an argument. That means the Except Method can also be used with Comparer also.

Let us understand this with an example:

LINQ Except Method in C# with Examples

As you can see in the above image, we have two data sources i.e. DataSource 1 and Data Source 2. The DataSource 1 contains elements such as 1, 2, 3, 4, 5, 6 and the DataSource 2 contains elements such as 1, 3, 5, 8, 9, and 10. If we want to retrieve the elements such as 2, 4, and 6 from the first data source which does not exist in the second data source then we need to apply the distinct operation.

Let us see how to do this with both Query and Method syntax.

Example1:
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.Except(dataSource2).ToList();
//Query Syntax
var QS = (from num in dataSource1
select num)
.Except(dataSource2).ToList();
foreach (var item in QS)
{
Console.WriteLine(item);
}
Console.ReadKey();
}
}
}

Run the application and you will see the output as expected.

Note: In query syntax, there is no such operator call Except, so here we need to use both query and method syntax to achieve the same.

Example2: 

Here we have a string array of countries and we need to return the countries from the first collection, those are not present in the second collection.

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.Except(dataSource2).ToList();
//Query Syntax
var QS = (from country in dataSource1
select country)
.Except(dataSource2).ToList();
foreach (var item in QS)
{
Console.WriteLine(item);
}
Console.ReadKey();
}
}
}

Now run the application and see the output.

In spite of having the country UK in the second collection, it still shows in the output. This is because the default comparer that is being used to filter the data is case-insensitive.

So if you want to ignore the case-sensitive then you need to use the other overloaded version of the Except() method which takes IEqualityComparer as an argument.

So, modify the program as shown where we pass StringComparer as an argument and this StringComparer class already implements the IEqualityComparer interface.

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.Except(dataSource2, StringComparer.OrdinalIgnoreCase).ToList();
//Query Syntax
var QS = (from country in dataSource1
select country)
.Except(dataSource2, StringComparer.OrdinalIgnoreCase).ToList();
foreach (var item in MS)
{
Console.WriteLine(item);
}
Console.ReadKey();
}
}
}

Now run the application and it will display the data as expected.

LINQ Except() Method with Complex Type:

The LINQ Except() Method in C# works slightly different manner when working with complex types such as Employee, Product, 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 in 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 say, we have the following two data sources.

LINQ Except() Method with Complex Type

As you can see in the above image, we have two data sources. The first data source i.e. AllStudents hold the information of all the students while the second data source i.e. Class6Students hold the data of only the 6th class students.

Example3:

Our requirement is only to fetch all the student names from except the 6th class students. That means we need to fetch the student names from the AllStudents data source which are not present in the second data source i.e. Class6Students.

using System.Collections.Generic;
using System;
using System.Linq;
namespace LINQDemo
{
class Program
{
static void Main(string[] args)
{
List<Student> AllStudents = new List<Student>()
{
new Student {ID = 101, Name = "Preety" },
new Student {ID = 102, Name = "Sambit" },
new Student {ID = 103, Name = "Hina"},
new Student {ID = 104, Name = "Anurag"},
new Student {ID = 105, Name = "Pranaya"},
new Student {ID = 106, Name = "Santosh"},
};
List<Student> Class6Students = new List<Student>()
{
new Student {ID = 102, Name = "Sambit" },
new Student {ID = 104, Name = "Anurag"},
new Student {ID = 105, Name = "Pranaya"},
};
//Method Syntax
var MS = AllStudents.Select(x => x.Name).Except(Class6Students.Select(y => y.Name)).ToList();
//Query Syntax
var QS = (from std in AllStudents
select std.Name).Except(Class6Students.Select(y => y.Name)).ToList();
foreach (var name in MS)
{
Console.WriteLine(name);
}
Console.ReadKey();
}
}
}

Output:

Example4:

Now we need to select all the information of all the students from the first data source which are not present in the second data source. 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> AllStudents = new List<Student>()
{
new Student {ID = 101, Name = "Preety" },
new Student {ID = 102, Name = "Sambit" },
new Student {ID = 103, Name = "Hina"},
new Student {ID = 104, Name = "Anurag"},
new Student {ID = 105, Name = "Pranaya"},
new Student {ID = 106, Name = "Santosh"},
};
List<Student> Class6Students = new List<Student>()
{
new Student {ID = 102, Name = "Sambit" },
new Student {ID = 104, Name = "Anurag"},
new Student {ID = 105, Name = "Pranaya"},
};
//Method Syntax
var MS = AllStudents.Except(Class6Students).ToList();
//Query Syntax
var QS = (from std in AllStudents
select std).Except(Class6Students).ToList();
foreach (var student in MS)
{
Console.WriteLine($" ID : {student.ID} Name : {student.Name}");
}
Console.ReadKey();
}
}
}

Output:

As you can see, it displays all the students data from the first data source. This is because the default comparer which is used for comparison is only checking whether two object references are equal and not the individual property values of the complex object.

In our previous Video, we already discussed there many ways to solve the above problem. Here let us see how to use an anonymous type to solve the above problem.

Using Anonymous Type:

In this approach, we need to select all the individual properties to an anonymous type. The following program does exactly the same things.

using System.Collections.Generic;
using System;
using System.Linq;
namespace LINQDemo
{
class Program
{
static void Main(string[] args)
{
List<Student> AllStudents = new List<Student>()
{
new Student {ID = 101, Name = "Preety" },
new Student {ID = 102, Name = "Sambit" },
new Student {ID = 103, Name = "Hina"},
new Student {ID = 104, Name = "Anurag"},
new Student {ID = 105, Name = "Pranaya"},
new Student {ID = 106, Name = "Santosh"},
};
List<Student> Class6Students = new List<Student>()
{
new Student {ID = 102, Name = "Sambit" },
new Student {ID = 104, Name = "Anurag"},
new Student {ID = 105, Name = "Pranaya"},
};
//Method Syntax
var MS = AllStudents.Select(x => new {x.ID, x.Name })
.Except(Class6Students.Select(x => new { x.ID, x.Name })).ToList();
//Query Syntax
var QS = (from std in AllStudents
select new { std.ID, std.Name})
.Except(Class6Students.Select(x => new { x.ID, x.Name })).ToList();
foreach (var student in QS)
{
Console.WriteLine($" ID : {student.ID} Name : {student.Name}");
}
Console.ReadKey();
}
}
}

Now run the application and it should display the output as expected. Let us see how to achieve the same thing using Comparer.

Using Comparer:

In this approach, we need to create a class and then we need to implement the IEqualityComparer interface. So, create a class file with the name StudentComparer.cs and then copy and paste the following code in it.

using System.Collections.Generic;
namespace LINQDemo
{
public class StudentComparer : IEqualityComparer<Student>
{
public bool Equals(Student x, Student y)
{
//First check if both object reference are equal then return true
if(object.ReferenceEquals(x, y))
{
return true;
}
//If either one of the object refernce is null, return false
if (object.ReferenceEquals(x,null) || object.ReferenceEquals(y, null))
{
return false;
}
//Comparing all the properties one by one
return x.ID == y.ID && x.Name == y.Name;
}
public int GetHashCode(Student obj)
{
//If obj is null then return 0
if (obj == null)
{
return 0;
}
//Get the ID hash code value
int IDHashCode = obj.ID.GetHashCode();
//Get the Name HashCode Value
int NameHashCode = obj.Name == null ? 0 : obj.Name.GetHashCode();
return IDHashCode ^ NameHashCode;
}
}
}

Then create an instance of StudentComparer class and pass that instance to the Except method as shown in the below program.

using System.Collections.Generic;
using System;
using System.Linq;
namespace LINQDemo
{
class Program
{
static void Main(string[] args)
{
List<Student> AllStudents = new List<Student>()
{
new Student {ID = 101, Name = "Preety" },
new Student {ID = 102, Name = "Sambit" },
new Student {ID = 103, Name = "Hina"},
new Student {ID = 104, Name = "Anurag"},
new Student {ID = 105, Name = "Pranaya"},
new Student {ID = 106, Name = "Santosh"},
};
List<Student> Class6Students = new List<Student>()
{
new Student {ID = 102, Name = "Sambit" },
new Student {ID = 104, Name = "Anurag"},
new Student {ID = 105, Name = "Pranaya"},
};
//Create an instance of StudentComparer
StudentComparer studentComparer = new StudentComparer();
//Method Syntax
var MS = AllStudents
.Except(Class6Students, studentComparer).ToList();
//Query Syntax
var QS = (from std in AllStudents
select std)
.Except(Class6Students, studentComparer).ToList();
foreach (var student in MS)
{
Console.WriteLine($" ID : {student.ID} Name : {student.Name}");
}
Console.ReadKey();
}
}
}

Now run the application and it should display the output as expected.

See All

Comments (464 Comments)

Submit Your Comment

See All Posts

Related Posts

Microsoft .Net 6 LINQ / Blog

What is Microsoft .Net 6 LINQ?

LINQ stands for Language-Integrated Query and it is a powerful query language that was introduced with .Net 3.5 & Visual Studio 2008. You can use LINQ with C# or VB to query different types of data sources such as SQL, XML, In memory objects, etc.
14-Feb-2022 /38 /464

Microsoft .Net 6 LINQ / Blog

What is Architecture of LINQ?

In this article, I am going to discuss the Architecture of LINQ. The term LINQ stands for Language Integrated Query and it is pronounced as LINK. Nowadays the use of use LINQ increasing rapidly. So, as a developer, you should understand the Linq and its architecture. At the end of this article, you will have a very good understanding of the following pointers.
14-Feb-2022 /38 /464

Microsoft .Net 6 LINQ / Blog

How to write Different Ways to Write LINQ Query?

In this article, I am going to discuss the Different Ways to write LINQ Query i.e. Linq Query Syntax and Linq Method Syntax with examples. Please read our previous article where we discussed the Architecture of LINQ i.e. how LINQ works. In this article, we are going to discuss the following pointers.
14-Feb-2022 /38 /464