C# LINQ Part 2


This entry is part 2 of 4 in the series C# LINQ

In this post on LINQ we will work with Mosh Hamedani and his video course on Udemy.com. With Linq, we can save ourselves writing code and shorten what we have. It makes our code easier to read. For example, if we had a list of Books and we want only a subset of the full list, we could write a for loop and iterate through the list and then when we find a book that meets a certain criteria we would add that book to a new list. That’s one example.

All of this can be reduced to one line of code using Linq. That’s powerful.

We can query lists of objects using a syntax similar SQL’s SELECT. These lists of objects could be anything, including our list of Books or Customers that we’ve talked about in other posts. So we could use Linq to return a list of books WHERE the price is less than a given price, and then ORDER BY the book’s price from smallest to largest. We can return a single object with SingleOrDefault. If we can’t find any objects and we’ve used SingleOrDefault, then the code will return Default, which is null. If we just use Single and we don’t find any, we get an exception, so SingleOrDefault is safer.

Or aggregate functions include Min, Max, Sum, Count and Average.

Let’s look at an example. We will use a simple Book class with two properties: Title and Price. We will also create a book repository

namespace Linq
{
    class Book
    {
        public string Title { get; set; }
        public float Price { get; set; }
    }
}

using System.Collections.Generic;
namespace Linq
{
    class BookRepository
    {
        public IEnumerable<Book> GetBooks()  // method
        {
            return new List<Book>
            {
                new Book() {Title = "ADO.NET Step by Step", Price = 5},
                new Book() {Title = "ASP.NET MVC", Price = 9.99f},
                new Book() {Title = "ASP.NET Web API", Price = 12},
                new Book() {Title = "C# Advanced Topics", Price = 7},
                new Book() {Title = "C# Advanced Topics", Price = 9}
            };
        }
    }
}

Without LINQ

using System.Collections.Generic;
namespace Linq
{
    class Program
    {
        static void Main(string[] args)
        {
            var books = new BookRepository().GetBooks();
            // Without LINQ:
            var cheapBooks = new List<Book>();
            foreach (var book in books)
            {
                if (book.Price < 10) cheapBooks.Add(book);
            }
            foreach (var book in cheapBooks) System.Console.WriteLine(book.Title + " " + book.Price);
        }
    }
}

With LINQ

using System;
using System.Linq;
namespace Linq
{
    class Program
    {
        static void Main(string[] args)
        {
            var books = new BookRepository().GetBooks();
            // With LINQ:
            var cheapBooks = books.Where(b => b.Price < 10);

            foreach (var book in cheapBooks)
            {
                Console.WriteLine(book.Title + " " + book.Price);
            }
        }
    }
}

Where()

Taking a closer look at Where() will reveal that it takes a delegate. We have posts here on delegates. How do we know this? We can use the Intelisense to show us what Where() expects. Have a glance at the screenshot below. Recall Lambda expressions.

Chaining

We can chain several together. They are processed from left to right. In the example code below we can see that we have Where, OrderBy and Select. First, Where filters out rows. Next OrderBy sorts the rows. Finally we Select which columns we want.

using System;
using System.Linq;
namespace Linq
{
    class Program
    {
        static void Main(string[] args)
        {
            var books = new BookRepository().GetBooks();
            // With LINQ:
            var cheapBooks = books
                .Where(b => b.Price < 10)
                .OrderBy(b => b.Price)
                .Select(b => b.Title);  // just a string now
            
            foreach (var book in cheapBooks)
            {
                Console.WriteLine(book);
            }
        }
    }
}
Series Navigation<< C# LINQ IntroductionC# LINQ Array of Integers >>