Conversion Operators in LINQ

The following are the conversion operators in LINQ:

  • ToList
  • ToArray
  • ToDictionary
  • ToLookup
  • Cast
  • OfType
  • AsEnumerable

But before going into any further details, we must learn what Deferred and Immediate Execution is.

LINQ operators can be categorized into the following.

Deferred or lazy operators: For example Select, Where, Take, Skip and so on.

Immediate operators: For example Count, Max, Min, Average, ToList and so on.

Let's look at an example of deferred execution.

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. namespace DeferredAndImmediate  
  5. {  
  6.     class Employee  
  7.     {  
  8.         public int Id{get;set;}  
  9.         public string Name {get;set;}  
  10.         public double Salary{get;set;}  
  11.     }  
  12.     class Program   
  13.     {  
  14.         static void Main(string[] args)  
  15.         {  
  16.             List < Employee > EmployeeList = new List < Employee > ()  
  17.             {  
  18.                 new Employee()   
  19.                 {  
  20.                     Id = 1, Name = "Sam", Salary = 41000  
  21.                 },  
  22.                 new Employee()   
  23.                 {  
  24.                     Id = 2, Name = "Max", Salary = 41000  
  25.                 },  
  26.                 new Employee()  
  27.                 {  
  28.                     Id = 3, Name = "Sara", Salary = 21000  
  29.                 }  
  30.             };  
  31.         }  
  32.     }  
  33. }  
Currently in my project I have a class “Employee” with three auto-implemented properties.

In the main method there is a list of employees.

Now let's say we want the records of all the employees whose salary is 41000.
  1. IEnumerable<Employee> employees = from employee in EmployeeList  
  2. where employee.Salary == 41000  
  3. select employee;  
To loop thru each employee we can use a foreach loop.
  1. foreach(Employee emp in employees)  
  2. {  
  3. Console.WriteLine(emp.Name);  
  4. }  
Now before running this application, let's understand where this program actually executes. What I am trying to say here is this program executes here.
  1. IEnumerable<Employee> employees = from employee in EmployeeList  
  2. where employee.Salary == 41000  
  3. select employee;  
  4. Or during the foreach loop.  
  5. foreach(Employee emp in employees)  
  6. {  
  7. Console.WriteLine(emp.Name);  
  8. }  
This program actually executes during the foreach loop and to prove that let's add another employee item to the list.



Run the application.



In the output we get three records which means the preceding query executes during the foreach loop that states this a deferred execution.

Now let's look at an example of immediate execution.
  1. IEnumerable<Employee> employees = (from employee in EmployeeList  
  2. where employee.Salary== 41000  
  3. select employee).ToList();  
  4. Convert the above linq query to a list.  
  5. EmployeeList.Add(new Employee() { Id = 4, Name = "Aiden", Salary = 41000 });  
  6. foreach(Employee emp in employees)   
  7. {  
  8. Console.WriteLine(emp.Name);  
  9. }
Run the application.



This time we got two records which means this ToList is an immediate execution operator.

Just like that count, max, min are immediate execution operators.

So, we now have some basic understanding of Deferred and Immediate execution. Let's dive right back to the conversion operator.

ToList

The ToList operator extracts items from the sequence and returns a new list back. This operator uses immediate execution.

DEMO
  1. static void Main(string[] args) {#region ToList  
  2.     //create array of integers  
  3.     int[] numbers =   
  4.     {  
  5.         1, 2, 3, 4, 5  
  6.     };  
  7.     //convert array to list which will return list of integers  
  8.     List < int > listNumber = numbers.ToList();  
  9.     //loop thru each list item  
  10.     foreach(int item in listNumber)   
  11.     {  
  12.         Console.WriteLine(item);  
  13.     }#endregion  
  14. }  
Run the application.



ToArray

This operator extracts items from a sequence and returns a new array. This operator causes immediate execution.

DEMO
  1. #region ToArray  
  2. //create a list of string  
  3. List < string > BrandList = new List < string > () {  
  4.     "Apple""Microsoft""Google""Samsung""Sony"  
  5. };  
  6. //retrieve items from the list in ascending order and convert them to array  
  7. string[] brandArray = (from brand in BrandList  
  8. orderby brand ascending  
  9. select brand).ToArray();  
  10. foreach(string item in brandArray)  
  11. {  
  12.     Console.WriteLine(item);  
  13. }#endregion  


ToDictionary

The ToDictionary operator executes the query, retrieves items from the sequence and returns a new dictionary object back. This operator is an immediate execution operator.

DEMO
  1. class Employee  
  2. {  
  3.     public int Id  
  4.     {get;set;}  
  5.     public string Name  
  6.     {get;set;}  
  7.     public double Salary  
  8.     {get;set;}  
  9. }  
  10. class Program  
  11. {  
  12.     static void Main(string[] args) {#region ToDictionary  
  13.         List < Employee > employeeList = new List < Employee > ()  
  14.         {  
  15.             new Employee()  
  16.             {  
  17.                 Id = 1, Name = "Sara", Salary = 41000  
  18.             },  
  19.             new Employee()  
  20.             {  
  21.                 Id = 2, Name = "Sam", Salary = 11000  
  22.             },  
  23.             new Employee()   
  24.             {  
  25.                 Id = 3, Name = "Aiden", Salary = 21000  
  26.             }  
  27.         };  
  28.   
  29.         Dictionary < int, Employee > employeeDic = employeeList.ToDictionary(x = > x.Id, y = > y);  
  30.         foreach(KeyValuePair < int, Employee > employee in employeeDic)  
  31.         {  
  32.             Console.WriteLine(employee.Key);  
  33.             Console.WriteLine(employee.Value.Name);  
  34.         }#endregion  
  35.     }  
  36. }  
Run the application.



ToLookup

Just like a dictionary, a Lookup is a collection of key/value pairs. The only difference between the two is a dictionary cannot contain keys with identical values whereas a lookup can.

DEMO
  1. class Employee   
  2. {  
  3.     public string Name   
  4.     {get;set;}  
  5.     public string JobTitle  
  6.     {get;set;}  
  7.     public string City  
  8.     {get;set;}  
  9. }  
  10. static void Main(string[] args) {#region ToLookup  
  11.     //create a list of employees  
  12.     List < Employee > employeeList = new List < Employee > ()  
  13.     {  
  14.         new Employee()   
  15.         {  
  16.             Name = "Aiden", JobTitle = "Sr. Developer", City = "London"  
  17.         },  
  18.         new Employee()  
  19.         {  
  20.             Name = "Max", JobTitle = "Developer", City = "Bangalore"  
  21.         },  
  22.         new Employee()   
  23.         {  
  24.             Name = "Sara", JobTitle = "Developer", City = "Bangalore"  
  25.         },  
  26.         new Employee()   
  27.         {  
  28.             Name = "Lara", JobTitle = "Sr. Developer", City = "London"  
  29.         },  
  30.         new Employee()   
  31.         {  
  32.             Name = "Michael", JobTitle = "Developer", City = "London"  
  33.         },  
  34.         new Employee()  
  35.         {  
  36.             Name = "Sam", JobTitle = "Developer", City = "London"  
  37.         }  
  38.     };  
  39.     //pass JobTitle as a key in the ToLookup method  
  40.     ILookup < string, Employee > employeeLookup = employeeList.ToLookup(x = > x.JobTitle);  
  41.     Console.WriteLine("Employee grouped by JobTitle");  
  42.     Console.WriteLine();  
  43.     //loop thru each items in employeelookup which will give IGrouping of key and value  
  44.     foreach(IGrouping < string, Employee > kvp in employeeLookup)   
  45.     {  
  46.         //print the key  
  47.         Console.WriteLine(kvp.Key);  
  48.         //add another foreach loop, using the key look for the items. This will return employee object back  
  49.         foreach(Employee emp in employeeLookup[kvp.Key])  
  50.         {  
  51.             Console.WriteLine("\t" + emp.Name + "\t" + emp.City);  
  52.         }  
  53.         Console.WriteLine();  
  54.     }#endregion  
  55. }  
Run the application.



Just like that we can even group them by city.
  1. ILookup < string, Employee > employeeLookup = employeeList.ToLookup(x = > x.City);  
  2. Console.WriteLine("Employee grouped by JobTitle");  
  3. Console.WriteLine();  
  4. foreach(IGrouping < string, Employee > kvp in employeeLookup)   
  5. {  
  6.     Console.WriteLine(kvp.Key);  
  7.     foreach(Employee emp in employeeLookup[kvp.Key])   
  8.     {  
  9.         Console.WriteLine("\t" + emp.Name + "\t" + emp.JobTitle);  
  10.     }  
  11.     Console.WriteLine();  
  12. }  
Run the application.



Cast

The Cast operator attempts to convert all the items within a collection to another type and return them in a new collection. If an item fails to convert then an exception is thrown. This cast method or operator uses deferred execution.

DEMO
  1. ArrayList al = new ArrayList();  
  2. al.Add(2);  
  3. al.Add(4);  
  4. al.Add(6);  
  5. al.Add(8);  
  6. IEnumerable<int> numbers = al.Cast<int>();  
  7. foreach(int item in numbers)  
  8.  {  
  9. Console.WriteLine(item);  
  10. }  
In the preceding demo, we creates an arraylist and this arraylist expects an item of type object.

Then using the cast operator we type-casted this arraylist object to an integer.

Run the application.



Let's add a new item to the same arraylist as in the following:

al.Add("9");

Run the application.



The first four numbers were printed but the fifth item throws an exception since this fifth item is of type string and the cast operator was not able to cast it into an integer.

So, always use this cast operator where a collection item will return a specified data type.

ofType

The OfType operator will only return the items of the specified type and other items will be excluded from the result set. This OfType uses deferred execution.

Demo
  1. ArrayList al = new ArrayList();  
  2. al.Add(2);  
  3. al.Add(4);  
  4. al.Add(6);  
  5. al.Add(8);  
  6. al.Add("9");  
  7. IEnumerable<int> numbers = al.OfType<int>();  
  8. foreach(int item in numbers)  
  9. {  
  10. Console.WriteLine(item);  
  11. }  
In the preceding demo we have a arraylist in which we have four integer items and one string item.

Run the application.



We got only the integer value back because this OfType operator will always return only the specified data type items back.

AsEnumerable

Use the AsEnumerable operator to move query processing to the client side.

This AsEnumerable operator breaks the query into the following two parts: 
  1. The first is the inside part in other words before AsEnumerable that gets executed as LINQ to SQL.
  2. The second is the outside part in other words after AsEnumerable that gets executed as LINQ to Objects.

Let's look at an example.

For the demo we will be using the following table.



Query for this table

  1. CREATE DATABASE db_AsQueryable  
  2. GO  
  3. USE db_AsQueryable  
  4. Create Table Employees  
  5. (  
  6. ID int primary key identity,  
  7. Name nvarchar(50),  
  8. Gender nvarchar(50),  
  9. Salary int  
  10. )  
  11. GO  
  12. Insert into Employees Values('Mark','Male','60000')  
  13. Insert into Employees Values('Steve','Male','45000')  
  14. Insert into Employees Values('Ben','Male','70000')  
  15. Insert into Employees Values('Philip','Male','45000')  
  16. Insert into Employees Values('Mary','Female','30000')  
  17. Insert into Employees Values('Valarie','Female','35000')  
  18. Insert into Employees Values('John','Male','80000')  
  19. Insert into Employees Values('Pam','Female','85000')  
  20. Insert into Employees Values('Stacey','Female','65000')  
  21. Insert into Employees Values('Andy','Male','73000')  
  22. Insert into Employees Values('Edward','Male','65000')  
  23. GO  
Step 1

Add a LINQ to SQL data model.



Click Add

Navigate to server explorer from view and click on connect to database.

Specify the server name and database.



Drag and drop the table to the designer window.



Step 2

In the main method of your project add the following.
  1. EmployeeDBDataContext employee = new EmployeeDBDataContext();  
  2. var emp = employee.Employees.Where(x => x.Gender == "Male").OrderByDescending(x => x.Salary).Take(5);  
  3. foreach(var item in emp)  
  4. {  
  5. Console.WriteLine(item.Name + "\t" + item.Gender + "\t" + item.Salary);  
  6. }  
Step 3

Open SQL Server -> open SQL Server profiler then run the console application.



In the SQL Server profiler look at the codes that got generated that executes and gave us the result.



Now just after the employees property and before the where operator invoke the AsEnumerable operator and re-run the application.
  1. var emp = employee.Employees.AsEnumerable().Where(x => x.Gender == "Male").OrderByDescending(x => x.Salary).Take(5);  
The output will remain the same.



But in the SQL Server profiler look at the code that was generated.



As very simple select statement and there are nowhere, orderby and top clause.The reason is that this AsEnuermable operator divides the query into two parts. One is the internal part that is before the AsEnumerable is executed using LINQ to SQL whereas the outer part is executed using the LINQ to object client-side memory datasets.

I hope you like it.

Thank you.