Getting Started with LINQ in C# (1/3)

Language Integrated Query or LINQ is a C# feature that allows you to query different data sources, such as:

In memory collections (arrays, lists, dictionaries)
SQL collections
XML collections

using a unified language syntax.

There are two ways to …


This content originally appeared on DEV Community and was authored by Mirza Leka

Language Integrated Query or LINQ is a C# feature that allows you to query different data sources, such as:

  • In memory collections (arrays, lists, dictionaries)
  • SQL collections
  • XML collections

using a unified language syntax.

There are two ways to use LINQ:

  • Query syntax consist of a set of query keywords defined into the .NET Framework that resemble SQL-Like commands.
  • Method syntax consist of operator functions (extension methods) chained together using a declarative programming paradigm.

For this tutorial we'll use LINQ Extension method syntax.

Where can we use LINQ?

Language Integrated Query syntax works with any type of collection in C# that implements the IEnumerable interface, such as arrays, lists, dictionaries, etc. Simply put, whenever you see a type IEnumerable or type that implements the IEnumerable, you can use LINQ.

Setup

To speed things up, I've already created a collection ot students in the JSON file. The Gist I wrote will explain how to import the JSON data into a C# collection.

Each student is a class containing properties:

public class Student
{
    public int ID { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
    public string Country { get; set; }
}
var student = new LINQTutorial();
List<Student> students = student.GetStudents();

The method GetStudents() on the student instance retrieves a collection of students populated using the JSON file. More in the Gist.

Now let's make use of various LINQ Operators to query the students data.

FILTERS

First & Last

The First() operator returns the first record in the collection:

var firstStudent = students.First();

Console.WriteLine($"Name: {firstStudent.Name}, Age: {firstStudent.Age}, Country: {firstStudent.Country}");
// Name: Mirza, Age: 18, Country: Bosnia

The opposite of First() is the Last() operator that returns the last record:

var lastStudent = students.Last();

Console.WriteLine($"Name: {lastStudent.Name}, Age: {lastStudent.Age}, Country: {lastStudent.Country}");
// Name: Amy, Age: 21, Country: USA

This is one way of using First() and Last() operators. The LINQ operators have an overload method that accepts a predicate and return the record/s that match the condition inside.

var firstStudent = students.First(x => x.Age == 19);

Console.WriteLine($"Name: {firstStudent.Name}, Age: {firstStudent.Age}, Country: {firstStudent.Country}");
// Name: Alan, Age: 19, Country: UK

var lastStudent = students.Last(x => x.Age == 20);

Console.WriteLine($"Name: {lastStudent.Name}, Age: {lastStudent.Age}, Country: {lastStudent.Country}");
// Name: Raj, Age: 20, Country: India

First/Last Or Default

What would happen if we'd query for first student with the age of 100?

var firstStudent = students.First(x => x.Age == 100);

Because there is no record of a student with age 100, the C# program execution will stop and throw an exception:

System.InvalidOperationException: Sequence contains no matching element

To prevent this we can use the FirstOrDefault() operator that works just the same as the First(), with an exception that it returns null if no record meets the condition.

var firstStudent = students.FirstOrDefault(x => x.Age == 19); // {...} 
var nonExistingStudent = students.FirstOrDefault(x => x.Age == 100); // null

The same applies for the Last() and LastOrDefault() operators.

ElementAt

This method is used to retrieve an element at a specific index.

var fifthStudent = students.ElementAt(4);

Console.WriteLine($"Name: {fifthStudent.Name}, Age: {fifthStudent.Age}");
// Name: Farook, Age: 18

That said, if you use an index that is not present, the exception will be thrown:

var nonExistingStudent = students.ElementAt(100);
System.ArgumentOutOfRangeException: Index was out of range. 

So it's safer to use ElementAtOrDefault:

var nonExistingStudent = students.ElementAtOrDefault(100); // null

Where

The Where() operator is used to filter multiple elements. The output is an array of all elements that meet a specified criteria.

var studentsFromBosnia = students.Where(x => x.Country == "Bosnia");

foreach (var student in studentsFromBosnia)
{
    Console.WriteLine($"Name: {student.Name}, Age: {student.Age}");
}
// Name: Mirza, Age: 18
// Name: Armin, Age: 20

One thing to note about studentsFromBosnia is that is not of type List<Student>, but rather IEnumerable<Student>. The LINQ works in either way.

However, if you need to pass this collection to a method that takes an array or a list as a parameter, you can cast an IEnumerable to derived types.

BUILDERS

To convert an IEnumerable to an array simply do:

var studentsArray = studentsFromBosnia.ToArray(); 
// Array<Student>

To convert an IEnumerable to a list simply do:

var studentsList = studentsFromBosnia.ToList(); 
// List<Student>

To convert an IEnumerable collection to a dictionary, first restructure the data into an anonymous key-value pair object and then covert the object to dictionary.

var studentsDictionary = studentsFromBosnia
  .Select((stud, index) => new { index, stud }) // creating an anonymous object
  .ToDictionary(x => x.index, x => x.stud); // converting object to dictionary
// Dictionary<int, Student>

PROJECTION

Select

The Select operator is used to retrieve a list of specific properties from an IEnumerable, in this case List. For example, let's say we want to pick names of all students:

IEnumerable<string> names = students.Select(s => s.Name);

foreach (var name in names)
{
    Console.WriteLine(name); 
    // Mirza, Armin, Alan, Seid...
}

Or a combination of properties (Name & Country):

var customList = students.Select(s => new { Name = s.Name, Country = s.Country });

foreach (var student in customList)
{
    Console.WriteLine($"Name: {student.Name}, Country: {student.Country}");
}

custom-select

SORTING

OrderBy

The OrderBy operator is used to order elements in the collections. For example, if we'd take ages of all students and put them into a collection:

var ages = students.Select(s => s.Age);

The outcome would be a collection sorted in the order the students were created. Applying the OrderBy, the ages are shown from smallest to largest:

var agesInOrder = students.OrderBy(s => s.Age).Select(s => s.Age);
// [18, 18, 18, 19, 19, 20, 20, 21, 22, 24]

It's clear that we have duplicate elements. We can fix that using the Distinct() operator:

var agesInOrder = students.OrderBy(s => s.Age).Select(s => s.Age).Distint();
// [18, 19,20, 21, 22, 24]

The OrderBy operator can also be applied after the Select:

var agesInOrder = students
    .Select(s => s.Age)
    .OrderBy(s => s) // sort by values in the collection (ages)
    .Distinct();
// [18, 19,20, 21, 22, 24]

In this instance, the ordering by ages is still hapening, but because we've already filtered the ages in the previous line, the OrderBy has less work to do.

OrderByDescending

The OrderbyDescending is doing the same but in the reversed order:

var agesInReverseOrder = students
    .Select(s => s.Age)
    .OrderByDescending(s => s)
    .Distinct();
// [24, 22, 21, 20, 19, 18]

ThenBy, ThenByDescending

The ThenBy operator is used to apply the additional sorting after the OrderBy.

var orderedByAgeAndCountry = students
    .OrderBy(s => s.Age)
    .ThenBy(s => s.Country)
    .Select(s => s.Name);
// ["Mirza", "Eddy", "Farook", "Abdurahman", "Alan"...]

var orderedByAgeAndCountry2 = students
    .OrderBy(s => s.Age)
    .ThenByDescending(s => s.Country)
    .Select(s => s.Name);
// ["Farook", "Eddy", "Mirza", ...]

In the coming parts we'll dive deeper into LINQ. Don't forget to hit the follow button. Also, follow me on Twitter to stay up to date with my upcoming content.

Bye for now 👋


This content originally appeared on DEV Community and was authored by Mirza Leka


Print Share Comment Cite Upload Translate Updates
APA

Mirza Leka | Sciencx (2024-07-28T10:55:02+00:00) Getting Started with LINQ in C# (1/3). Retrieved from https://www.scien.cx/2024/07/28/getting-started-with-linq-in-c-1-3/

MLA
" » Getting Started with LINQ in C# (1/3)." Mirza Leka | Sciencx - Sunday July 28, 2024, https://www.scien.cx/2024/07/28/getting-started-with-linq-in-c-1-3/
HARVARD
Mirza Leka | Sciencx Sunday July 28, 2024 » Getting Started with LINQ in C# (1/3)., viewed ,<https://www.scien.cx/2024/07/28/getting-started-with-linq-in-c-1-3/>
VANCOUVER
Mirza Leka | Sciencx - » Getting Started with LINQ in C# (1/3). [Internet]. [Accessed ]. Available from: https://www.scien.cx/2024/07/28/getting-started-with-linq-in-c-1-3/
CHICAGO
" » Getting Started with LINQ in C# (1/3)." Mirza Leka | Sciencx - Accessed . https://www.scien.cx/2024/07/28/getting-started-with-linq-in-c-1-3/
IEEE
" » Getting Started with LINQ in C# (1/3)." Mirza Leka | Sciencx [Online]. Available: https://www.scien.cx/2024/07/28/getting-started-with-linq-in-c-1-3/. [Accessed: ]
rf:citation
» Getting Started with LINQ in C# (1/3) | Mirza Leka | Sciencx | https://www.scien.cx/2024/07/28/getting-started-with-linq-in-c-1-3/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.