C# - Introduction to LINQ

Users who viewed this discussion (Total:0)

Rating - 0%
0   0   0
#1
C# - Introduction to LINQ
Skill level: Intermediate
Prior knowledge assumed: Generics, Arrays, Lambda Expressions
This is a tutorial aimed at members who have a grasp on the language, if you don't then this tutorial is not for you

What is LINQ?
LINQ, standing for Language-integrated query, is a tool to extract specific items out of collections. It is most commonly used with basic lists and arrays, but it's also usable for Entity DB and other database solutions too. It's a bit similar to the SQL SELECT function but it can be immensely powerful. Let's jump straight in.
Say you're pulling an array of different cars from somewhere, maybe a database. I'm going to hard-code it for the sake of this tutorial. (This project is available on my dropbox at the end of this tutorial, so the Car struct is available there.)
Code:
var carsList = new[] {
    new Car() { Manufacturer = "Honda", Model = "Accord", MilesPerGallon = 40, Cost = 18500, PaintColor = Color.Silver, Automatic = false },
    new Car() { Manufacturer = "Seat", Model = "Ibiza", MilesPerGallon = 55, Cost = 13500, PaintColor = Color.Red, Automatic = false },
    new Car() { Manufacturer = "Seat", Model = "Leon", MilesPerGallon = 45, Cost = 15500, PaintColor = Color.Blue, Automatic = true },
    new Car() { Manufacturer = "Vauxhall", Model = "Vectra", MilesPerGallon = 50, Cost = 20000, PaintColor = Color.Blue, Automatic = false },
    new Car() { Manufacturer = "Ford", Model = "Ka", MilesPerGallon = 65, Cost = 9500, PaintColor = Color.Red, Automatic = false },
    new Car() { Manufacturer = "Volkswagen", Model = "Passat", MilesPerGallon = 50, Cost = 17000, PaintColor = Color.Black, Automatic = true },
    new Car() { Manufacturer = "Volkswagen", Model = "Golf", MilesPerGallon = 60, Cost = 11000, PaintColor = Color.Silver, Automatic = false },
    new Car() { Manufacturer = "Land Rover", Model = "Defender", MilesPerGallon = 25, Cost = 24000, PaintColor = Color.Silver, Automatic = false },
    new Car() { Manufacturer = "Peugeot", Model = "406", MilesPerGallon = 50, Cost = 15000, PaintColor = Color.Green, Automatic = false },
    new Car() { Manufacturer = "Porsche", Model = "Boxster", MilesPerGallon = 34, Cost = 38000, PaintColor = Color.Yellow, Automatic = false },
    new Car() { Manufacturer = "Ford", Model = "Focus", MilesPerGallon = 45, Cost = 13000, PaintColor = Color.Red, Automatic = false },
    new Car() { Manufacturer = "Vauxhall", Model = "Corsa", MilesPerGallon = 40, Cost = 14500, PaintColor = Color.Black, Automatic = true }
};
Okay, so we have a list of Cars. But what if we only wanted to get the manual-transmission cars? How would you do this without LINQ? You might make a temporary list, use a foreach() loop to iterate through carsList and then use an if statement to add any cars where Automatic == false to the list. But that's painful and doesn't look clean. This is where LINQ comes in. There are two ways of writing LINQ - the method way and the query-style way - this tutorial will use the method way because it has more features.

How do I use it?
Let's start simple and go with the previous example. Let's get a collection of all of the manual-transmission cars.
Code:
var manualCars = carsList
    .Where(car => car.Automatic == false);
You should see the Lambda expression straight away. This passes a lambda-expression to the .Where() method, which returns true if the given car is not automatic. What LINQ methods do is go through each element in the array or collection, and apply the lambda-expression to it - notice how the expression takes a singular Car, not an array. The expression is ran for each Car item in the array we give. The method will then return all the items which satisfy that condition. This code could all be on the same line, but once you start to chain methods together it's cleaner to put one on each line.
Note that .Where() takes a predicate, which means the lambda-expression takes one parameter and returns a boolean.

Let's go for another example. We only want cars that are red.
Code:
var redCars = carsList
    .Where(car => car.PaintColor == Color.Red)
This is similar to the above example. It explains itself.

What if we want all of the cheaper cars?
Code:
var cheapCars = carsList
    .Where(car => car.Cost < 15000);
Remember that the < operator just returns a boolean, so this still works.

Okay, I'm sick of .Where(). Let's use something different. What if we want a list of different car manufacturers?
Code:
var carManufacturers = carsList
    .Select(car => car.Manufacturer);
There's a new function - .Select(). This is very flexible, because it can return anything. In this case, it will take a Car structure and return only the Manufacturer property of it. Cool, huh? It's like it extracts one property out of the structure and brings it forward. It doesn't necessarily have to be a property - you could do anything with the object; you could even do:
Code:
var uselessList = carsList
    .Select(car => false);
which would only ever return false. Why you'd want to is beyond me, but it's possible.

There's an issue with the previous example though. The list of car manufacturers has some duplicates. There will be two copies of Seat, Volkswagen and Vauxhall. We can introduce another new function, and another idea:
Code:
var carManufacturers = carsList
    .Select(car => car.Manufacturer)
    .Distinct();
That's interesting. We have two methods after one another. This is called chaining. The .Select() method returns a LINQ collection and the .Distinct() method takes one, as do most LINQ functions, so theoretically you could chain a hundred of these together.
Anyway, the .Distinct() method just removes any duplicates. It takes no parameters.

Something to take notice of, is that .Select(), .Where() and .Distinct() are all extension methods. If you remove the 'using System.Linq;' from the top of your code file, you can't use LINQ any more. Something to be careful of if you're using .NET 2.0 or below, because System.Linq doesn't exist there.

Now we've covered the basics of what LINQ is I'd like to link you to this. There are so many LINQ extension methods that trying to remember all of them is a pointless exercise. You could either use that page, which documents all of the functions, or just use Visual Studio's IntelliSense if you're feeling adventurous and can work out the way to use the methods yourself, which is definitely possible if you're an advanced C# programmer.

Lastly, the reason I've been using var in those previous snippets of code is because the LINQ methods don't return an array. They return a Collection that has special properties, of which I might cover in a later Advanced LINQ tutorial, if there ever is one. You can either use a foreach() loop to iterate over, say, carManufacturers like an array, or use the handy LINQ function .ToArray() to convert it to a nice old array again, which might be useful for you.

Exercises
  • Use LINQ to create a var called notBlueCars which contains all of the cars which are not blue.
  • Use LINQ to create a var called econonicalCars which contains all of the cars which do 45MPG or above.
  • Use LINQ to create a var called carColors which contains all of the possible colours of cars, without any duplicates.
  • (Advanced) Use LINQ to create a var called sortedCarManufacturers

I may consider a series of tutorials to teach the language when I have some more free time.
 

Top