LINQ stands for Language-Integated Queries. LINQ is a technology that helps in using query capabilities and integrations in C# directly. The importance of LINQ in C# has increased tremendously with the introduction of Entity Framework as a powerful ORM for developing database interactive applications in .NET technologies.
LINQ generally operates on the collection types in C# and comes with some great extension methods which serve a variety of purposes in working with collections of types. These are so well integrated in our development that we sometimes forget that we’re using a LINQ method in our applications while actually using them.
In this article, let’s look at the top LINQ methods we use in our everyday C# programming.
Setting up the Example
To understand how these methods work better, let’s put together a simple complex type that mimics an entity. We’ll define a class variable that holds our collection, and we’ll use this variable in our lookout.
internal class Hero
{
public int Id { get; set; }
public string Name { get; set; }
public List<string> Capabilities { get; set; }
public string Bio { get; set; }
}
public class LinqHelper
{
private readonly List<Hero> heroes;
public LinqHelper()
{
this.heroes = SeedHeroes().ToList();
}
private IEnumerable<Hero> SeedHeroes()
{
for (int i = 1001; i <= 1100; i++)
{
yield return new Hero
{
Id = i,
Name = $"Hero#{i}",
Bio = $"Boku va Hero#{i}. Save the world.",
Capabilities = new List<string>() {
$"Fly#{i}", $"Kick#{i}", $"Punch#{i}"
}
};
}
}
}
Top 10 LINQ methods we use in our everyday C# programming
1. First()
First() method returns the “first” element in the collection, for an optional condition. If a condition is passed to the function as a predicate, the method returns the first element in the list which satisfies the predicate function. If no elements satisfy the condition, it throws an exception.
public void FirstHeroWithIdMultipleOf101()
{
// throws exception
var firstHeroWithIdMultipleOf101 = this.heroes.First(x => x.Id % 101 == 0);
}
This method is useful when we’re working with collections and would like to handle the scenario where there are no elements for the condition by ourselves.
2. FirstOrDefault()
FirstOrDefault() works in a similar fashion as the First() method for positive cases in a collection – it returns the first element in the collection which satisfy an optional condition. The difference is in the negative case where there are no elements that satisfy the condition or the collection is empty – the method returns the default value for that type: NULL for reference types and respective default value for value types.
public void FirstHeroWithIdMultipleOf101()
{
// returns NULL
var withDefault = this.heroes.FirstOrDefault(x => x.Id % 101 == 0);
}
3. Single()
Single() method returns the only element in the collection which satisfies a given condition. The rule is that there should be only a single element in the collection which satisfies the condition – for example a primary key in a table which is one and unique. If there are more than one elements which satisfy the condition for the Single() method, it throws an exception.
public void SingleHeroWithIdMultipleOf100()
{
// throws exception
var singleHeroWithIdMultipleOf10 = this.heroes.Single(x => x.Id % 10 == 0);
}
This method is useful in the cases where we are strict about our case and would want to handle erroneous case by ourselves.
4. SingleOrDefault()
SingleOrDefault() method works similar to Single() method in the positive case – returns the only element which satisfies a given condition. But when this condition returns more than one element or the collection is empty, the method returns a default value – NULL for a reference type and respective default value for a value type.
public void SingleHeroWithIdMultipleOf100()
{
// returns NULL
var withDefault = this.heroes.SingleOrDefault(x => x.Id % 100 == 0);
}
5. Any()
The Any() method returns a boolen value. The method just returns if there exists any element in the collection, which satisfies an optional condition. If no condition is provided, the method just returns if the collection is empty or not.
public void AnyHeroWithIdMultipleOf101()
{
// returns false
var anyHeroWithIdMultipleOf101 = this.heroes.Any(x => x.Id % 101 == 0);
// returns true
var anyHeroWithIdMultipleOf100 = this.heroes.Any(x => x.Id % 100 == 0);
}
6. Select()
The Select() method helps in projecting or mapping each element of the collection into a new sequence. If the elements of the collection are complex types (such as classes) consisting of properties, the method can be used to project one or more specific properties of each element in the collection into a new collection of elements.
public void SelectSpecificColumnsFromHeroes()
{
var selectSpecificColumnsFromHeroes = this.heroes.Select(x => new
{
x.Id,
x.Name,
x.Bio
});
// LINQ query syntax
var selectSpecificColumnsFromHeroesQuery = from r in this.heroes
select new { r.Id, r.Name, r.Bio };
// project single property
IEnumerable<int> selectSingleColumnFromHeroes = this.heroes.Select(x => x.Id);
// LINQ query syntax
IEnumerable<List<string>> selectSingleColumnFromHeroesQuery = from r in this.heroes
select r.Capabilities;
}
In the first set of select results, we project specific properties from every Hero type element inside the collection to form a new collection. This resultant collection is a sequence of anonymous types which all have three properties – Id, Name and Bio. A cleaner approach for this to project these properties into an equivalent predefined type.
In the second set of select results, we project a single property Id from every Hero element in the collection, which results in a collection of integer types.
One can use the Select() method as a method or as a LINQ query as shown in the above function. The LINQ query syntax looks similar to an SQL syntax, and when used in database oriented operations (such as in EFCore using DbConext), this query syntax is translated into an equivalent SQL query and executed on the database.
7. Where()
Where() method returns all the elements from the collection which satisfy a given condition. One major difference between Where(), First() and Single() is that while Single() and First() methods return a single element from the collection, the Where() method returns all the elements in the collection for that condition that is passed for all these three methods.
public void QueryHeroesWithOddIds()
{
var oddHeroes = this.heroes.Where(x => x.Id % 2 != 0);
// LINQ query syntax
var oddHeroesQuery = from r in this.heroes
where r.Id % 2 != 0 select r;
}
One can use the Where() method as a method or inside a LINQ query complementing the Select() method as shown above. We can also apply projection on the elements returned by a Where() method by chaining a Select() to the Where() method.
this.heroes.Where(x => x.Id % 2 != 0)
.Select(x => new { x.Id, x.Name, x.Bio });
8. OrderBy()
OrderBy() method sorts the elements in a given collection in ascending order based on a given condition and returns the sorted collection. If we have to sort a collection of complex types based on more than one property of the elements, we can do so by chaining another function to OrderBy() called ThenBy().
public void SelectHeroesOrderedById()
{
// ascending order
var selectHeroesWithOrderById = this.heroes.OrderBy(x => x.Id)
.ThenBy(x => x.Name);
// LINQ query syntax
var selectHeroesWithOrderByIdQuery = from r in this.heroes
orderby r.Id, r.Name
select r;
}
One can use the OrderBy() and ThenBy() method or use an equivalent LINQ query syntax as shown above.
9. OrderByDescending()
OrderByDescending() method is similar to OrderBy() method, except that the collection is sorted in a descending order. To sort based on more than one columns, one can use ThenByDescending() method chained to the OrderBy() method or use an equivalent LINQ syntax as shown below:
public void SelectHeroesOrderedByIdDescending()
{
// descending order
var selectHeroesWithOrderByIdDesc = this.heroes.OrderByDescending(x => x.Id)
.ThenByDescending(x => x.Name);
// LINQ query syntax
var selectHeroesWithOrderByIdDescQuery = from r in this.heroes
orderby r.Id descending, r.Name descending
select r;
}
10. ToList()
ToList() method one of the most subsconsciously used LINQ methods in all our journeys with collections. ToList() method takes in an IEnumerable type and converts it to a List type. This conversion is important in cases where we would want to use a concrete type “List” in place of an abstract “IEnumerable” or when we want to use the methods available in a “List” type over a collection of an abstract type.
“All the LINQ methods we discussed above return an abstract IEnumerable collection, which we might be interested to perform more operations later on. For that we use ToList() to convert to an equivalent List of the processed elements.”
var selectHeroesWithOrderByIdDesc = this.heroes.OrderByDescending(x => x.Id)
.ThenByDescending(x => x.Name);
ToList() also results in an “Eager Evalution” of the LINQ syntax which does a “Lazy Evalution” by default. This is important in the cases of a database query operation in DbConext or EFCore where a LINQ-to-SQL translation occurs, or in the case of a “yield” keyword.
List<Hero> heroes = this.heroes.Where(x => x.Id % 2 != 0)
.Select(x => x).ToList();
// LINQ query syntax
List<Hero> heroes = (from r in this.heroes
where x.Id % 2 != 0
select r).ToList();
Found this article helpful? Please consider supporting!
Bonus: ToDictionary()
ToDictionary() is another useful method which can create a Dictionary of Key Values from an input collection of elements. For example, if we want to create a Dictionary of our Hero elements from the collection with the HeroId as the Key and the object as the value, we can use this method as below:
public void DictionaryOfHeroes()
{
Dictionary<int, Hero> heroDictionary = this.heroes
.ToDictionary(key => key.Id, value => value);
}
Another best example where we use a ToDictionary() is when we want to read the headers of an incoming request and process them.
Dictionary<string, string> headers = context.Request.Headers
.ToDictionary(x => x.Key, x => x.Value.ToString());
These are the top LINQ methods we generally use in our everyday C# programming. Which ones do you use the most?
I think there’s a goof in #4. SingleOrDefault() throws an exception if more than one element are returned.