My Top 5 Most Used LINQ Methods in C#
What is LINQ?
LINQ is 'Language Integrated Query'. LINQ queries allow you to extract data from enumerables (lists, arrays, etc.) in a similar way to how you'd query a database with SQL.
This was introduced in 2007, so it's been around for a while, and it gives you an alternative to for loops. It's not quicker than using loops, since it's doing loops under the hood anyway, but it makes your code more readable and easier to maintain (although people will argue both sides of this). I'll give examples of both ways of doing it so you can compare the syntax and make your own mind up (foreaches btw, not full for loops since full for loops are pretty rare these days).
All the examples are in the method syntax because it's much more lean and in keeping with the rest of the c# style than the query syntax. The method syntax uses lambda expressions, which I'm not going to explain here because you should be able to recognise the pattern and experiment with LINQ without knowing the ins and outs of lambdas. Obvs go look it up at some point though. Knowledge is power.
All these examples will be based on a string list containing names. It's stored in a variable called 'names'. We'll use the LINQ queries to get different results from the same list. If you're interested, the code to generate the list is this:
1 - .Where
This should be used when you need a list of values that match a certain criteria. For example, I want to know which values in my list of names are less than 10 characters long.
Here is the foreach:
Here is the LINQ query:
.Where will return an IEnumerable, regardless of whether there is one result or multiple. If there are no matches, you get an empty IEnumerable.
Both the foreach and the LINQ query result in this list:
2 - .Any
This checks whether any items in the list match the condition. It's useful for validation before running further functions. For example, I want to know if any of the names contain the substring 'Penny'. If one does match, we'll send an email warning the rest of the people that there is a monster among them. If not, we'll just carry on as normal.
.Any returns a boolean. It's true if it hits a matching item. If it doesn't hit a matching item, it returns false. As soon as it hits its first matching item, it returns and won't check the rest of the items in the list.
Here is the foreach:
Here is the LINQ:
3 - .All
In the same vein as .Any, .All is useful for validation before moving on. .All checks whether all items in a list match the criteria. For example, if I was about to send an email to a list of email addresses, I might check that all the items in the list contained the '@' symbol before sending, to prevent any errors (fun fact - in Polish, the @ sign is called 'małpa', which means 'monkey').
.All returns false if one or more items don't match the criteria, and it'll return true if all items match the criteria.
In our example, let's check whether all the names have a first name and a last name. We'll do this by making sure all of the items have a space. This will return false because Pennywise does not have a space.
Here is the foreach:
Here is the LINQ:
4 - .Distinct
.Distinct will return an IEnumerable of all the unique items in the list. If there are no unique items, you get an empty IEnumerable. This one can be used with or without the lambda predicate. If you've got a list of simple types (like strings or ints), you don't need a predicate/condition as it will just look for unique values. However, if your list consists of complex objects, you can pass it a lambda condition in the same way as the examples above to check for distinct properties.
To illustrate this one, I've added some terror to the list:
Here is the foreach:
Here is the LINQ:
Here is the resulting list with only one inter-dimensional shapeshifter (phew):
5 - .Select
This one is slightly different to the rest. This takes each item in the list, does something to it and adds the result to a new list. Whatever function you pass will be executed on each item, and the result of the function will be added to a new list.
This one can expand into something really complicated, depending on what data you need and how complex the objects in your list are, so it's where you need to be aware of readability and maintainability. For the more simple uses, LINQ is more readable than for loops, but, as they get more complex, they can get much more messy. You'll need to weigh up whether a foreach would be more readable and kinder to the future devs who inherit your code.
Back to our example: I want to know the name, and the length of each name, so I pass in a lambda function that creates a KeyValuePair for each item, sets the name as the key, and the name's length as the value. It then adds the KVPs to an IEnumerable and returns it.
Here is the foreach:
Here is the LINQ:
Here is the resulting list:
It's a completely new list of type KeyValuePair<string, int>, not the initial list of type string. The original list has not been changed.
There are loads more LINQ functions, and, although I've not included them here, they're all useful and simplify data manipulation, so they're definitely worth delving into.
I'm always interested in what other devs are doing, so leave a comment and tell me how you use LINQ, what your favourite LINQ method is, where you stand on the LINQ vs Loop debate, or where you stand on the query syntax vs method syntax debate!
Subscribe to my newsletter
Read articles from Kate Brown directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by