|
Introduction to LINQ category 'KB', language C#, created 31-Aug-2025, version V1.0, by Luc Pattyn |
|
License: The author hereby grants you a worldwide, non-exclusive license to use and redistribute the files and the source code in the article in any way you see fit, provided you keep the copyright notice in place; when code modifications are applied, the notice must reflect that. The author retains copyright to the article, you may not republish or otherwise make available the article, in whole or in part, without the prior written consent of the author. Disclaimer: This work is provided |
LINQ operates on lists, i.e. any collection<T> that implements at least IEnumerable, IAsyncEnumerable or IQueryable.
Most collections do implement IEnumerable, e.g. arrays, List<T>, etc.
And when they do, you can easily enumerate all elements of the collection using a foreach loop.
LINQ has two different syntaxes:
The officially recommended way to write most queries is to use query syntax to create query expressions . This syntax resembles SQL syntax. I haven t used it yet. A good starting point could be:
I prefer the method syntax, where one concatenates operations one after the other and they will get executed left-to-right. This supports functional programming. Method syntax is used throughout this document.
LINQ methods may take parameters, such as:
Cond: an expression or function that generates a result of type
bool
Func: an expression or function that generates a result of type T
(sometimes TResult)
Comp: either a function that generates a number, or a classical
Comparer<T>
These are provided in the form of lambda expressions; one gets the current element (and optionally its sequence number or index ) in a local variable; examples:
coll.Where(x => x%2==0)
coll.Where( (x, index) => x != 0 && index%3 != 0)
What follows is an enumeration of the most popular LINQ methods. The complete list is available here: https://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable
Operations that transform the collection, i.e. the result is another, often smaller, collection normally of the same type T:
|
coll.Where(cond) |
elements that don t satisfy the boolean expression will be ignored |
|
coll.Append(T) |
append one element (since .NET Framework 4.7.1) |
|
coll.Select(func) |
replaces the collection by another collection holding the results of the func; these may be of a different type! |
|
coll.Take(int) |
returns
a specified number of contiguous elements from the start of a sequence |
|
coll.Skip(int) |
bypasses a specified number of elements |
|
coll.SkipWhile(cond) |
skips elements in list as long as condition is true and after that it will stop skipping |
|
coll.OrderBy(comp) |
sort the collection based on a comparer |
|
coll.ThenBy(comp) |
Performs a subsequent ordering |
|
coll.Reverse() |
Inverts
the order of the elements |
|
coll.AsEnumerable() |
This method has no effect other than to change the compile-time type of source from a type that implements IEnumerable<T> to IEnumerable<T> itself. Can be useful for some operations, e.g. when providing an alternative with the ?? operator. |
Export operations:
|
coll.ToList() |
returns a List<T> |
|
coll.ToArray() |
returns an array T[] |
|
coll.ToDictionary() |
creates a Dictionary |
|
coll.ToHashSet() |
Creates a HashSet<T> |
Operations that return a single element of type T or a value of type T; when the regular operation isn t possible, they return default(T) which often is null.
|
coll.First() |
returns the first element |
|
coll.First(cond) |
returns the first element that satisfies the bool expr |
|
coll.Last() |
returns the last element |
|
coll.Last(cond) |
returns the last element that satisfies the bool expr |
|
coll.ElementAt(index) |
returns the element at the specified index |
|
coll.Single() |
returns the single element (throws an exception when not exactly one element exists) |
|
coll.SingleOrDefault() |
returns the single element or default(T) (throws an exception when more than one element exists) |
Operations that return a single aggregate value of type TResult for a collection of type T which must be numeric; TResult may differ from T:
|
coll.Sum() |
returns the sum (T) |
|
coll.Average() |
returns the average value (T) |
|
coll.Max() |
returns the maximum value (T) |
|
coll.Max(func) |
returns the maximum value of the func (TResult) |
|
coll.Min() |
returns the minimum value (T) |
|
coll.Min(func) |
returns the minimum value of the func (TResult) |
Operations that return a single value (bool or int, not type T):
|
coll.All(cond) |
returns a bool: true if the bool expr is true for all elements |
|
coll.Any(cond) |
returns a bool: true if the bool expr is true for at least one element |
|
coll.Count() |
returns the number of elements |
|
coll.Count(cond) |
returns the number of elements satisfying the bool expr |
One cannot directly modify a collection while enumerating it, e.g. selectively removing some elements is not straightforward. Using a temporary second collection does work, like so:
foreach(T elem in coll.ToList())
if (someCond(elem)) coll.Remove(elem);
This can be optimized to:
foreach(T elem in coll.Where(elem=>someCond(elem)).ToList())
coll.Remove(elem);
as now the temporary list is shorter.
Now when coll is a List<T> to start with, there is the very useful method
coll.RemoveAll(elem => someCond(elem));
This is not LINQ as it does not work on IEnumerables, only on real List<T> objects.
The array class has a static ForEach method:
Array.ForEach(myArray, x => Console.WriteLine(x));
And instances of List<T> also support ForEach:
myList.ForEach(x
=> Console.WriteLine(x));
But IEnumerable doesn t offer ForEach.
ref https://stackoverflow.com/questions/529188/executing-a-certain-action-for-all-elements-in-an-enumerablet
Namespace System.Linq.Async offers similarsupport for enumerables that implement IAsyncEnumerable.
Read more about it here: https://www.codeproject.com/Articles/5319506/Getting-Started-With-Asynchronous-Streams
use OrderByDynamic, see
https://www.codeproject.com/Questions/987016/How-to-build-dynamic-order-by-clause-in-LINQ-query
When the property worked upon isn t constant, we need dynamic LINQ.
See The Workings of Dynamic Lambda in LINQ
https://www.codeproject.com/Articles/171749/The-Workings-of-Dynamic-Lambda-in-LINQ
Perceler |
Copyright © 2012, Luc Pattyn |
Last Modified 21-May-2025 |