Language Integrated Query (LINQ) is the C# feature set for querying data with C# syntax. Many LINQ operators use deferred execution: they describe the result first and read the data later, when your code asks for the results. A query describes which data to read and how to shape the result. A query reads from a data source. A data source can be an in-memory collection, such as an array or System.Collections.Generic.List, or an external source, such as a database or XML, exposed through a LINQ provider. A LINQ provider is a library that connects LINQ syntax to a specific kind of data source. This article uses in-memory collections for its examples. A sequence is an ordered set of elements represented by System.Collections.Generic.IEnumerable. For more information about provider-based queries, see Language Integrated Query (LINQ).
LINQ query expression syntax
The examples in this article read in-memory collections such as arrays and System.Collections.Generic.List. A query usually has three parts: specify the data source, describe the result, and enumerate the source to produce the result. To enumerate a sequence means to read its elements one at a time, often with foreach.
sample · csharpdocs/csharp/fundamentals/statements/snippets/linq-statements/Program.csQuerySyntax
namespace LinqStatements;
public static class Program
{
public static void Main()
{
QuerySyntaxExample();
MethodSyntaxExample();
QuerySyntaxClearerExample();
MethodSyntaxClearerExample();
LambdaExpressionsExample();
QuerySyntaxLambdaExample();
CommonOperatorsExample();
GroupByExample();
DeferredExecutionExample();
ImmediateExecutionExample();
ComposeQuerySyntaxExample();
ComposeMethodSyntaxExample();
ComposeWithCachingExample();
}
private static void QuerySyntaxExample()
{
// <QuerySyntax>
string[] names = ["Ana", "Ben", "Cleo", "Dara"];
IEnumerable<string> query =
from name in names
where name.Length >= 4
orderby name
select name;
foreach (string name in query)
{
Console.WriteLine(name);
}
// This example produces the following output:
//
// Cleo
// Dara
//
// </QuerySyntax>
}
private static void MethodSyntaxExample()
{
// <MethodSyntax>
string[] names = ["Ana", "Ben", "Cleo", "Dara"];
IEnumerable<string> query = names
.Where(name => name.Length >= 4)
.OrderBy(name => name)
.Select(name => name);
foreach (string name in query)
{
Console.WriteLine(name);
}
// This example produces the following output:
//
// Cleo
// Dara
//
// </MethodSyntax>
}
private static void QuerySyntaxClearerExample()
{
// <QuerySyntaxClearer>
(string Area, int Priority)[] workItems =
[
("docs", 2),
("tests", 1),
("deploy", 4),
("api", 1)
];
IEnumerable<string> nextItems =
from item in workItems
let label = $"{item.Area}: P{item.Priority}"
where item.Priority <= 2
orderby item.Priority, item.Area
select label;
foreach (string item in nextItems)
{
Console.WriteLine(item);
}
// This example produces the following output:
//
// api: P1
// tests: P1
// docs: P2
//
// </QuerySyntaxClearer>
}
private static void MethodSyntaxClearerExample()
{
// <MethodSyntaxClearer>
List<string> workItems = ["design", "docs", "deploy", "review"];
int count = workItems.Count(item => item.StartsWith('d'));
Console.WriteLine($"Starts with d: {count}"); // => Starts with d: 3
// </MethodSyntaxClearer>
}
private static void LambdaExpressionsExample()
{
// <LambdaExpressions>
string[] names = ["Ana", "Ben", "Cleo"];
IEnumerable<string> shortNames = names
.Where(name => name.Length == 3)
.Select(name => name.ToUpperInvariant());
foreach (string name in shortNames)
{
Console.WriteLine(name);
}
// This example produces the following output:
//
// ANA
// BEN
//
// </LambdaExpressions>
}
private static void QuerySyntaxLambdaExample()
{
// <QuerySyntaxLambda>
string[] workItems = ["docs", "test", "deploy"];
IEnumerable<string> querySyntax =
from item in workItems
where item.Length == 4
select item;
IEnumerable<string> methodSyntax =
workItems.Where(item => item.Length == 4);
foreach (string item in querySyntax)
{
Console.WriteLine($"Result: {item}");
}
foreach (string item in methodSyntax)
{
Console.WriteLine($"Result: {item}");
}
// This example produces the following output:
//
// Result: docs
// Result: test
// Result: docs
// Result: test
//
// </QuerySyntaxLambda>
}
private static void CommonOperatorsExample()
{
// <CommonOperators>
Dictionary<string, int> priorities = new()
{
["Docs"] = 2,
["Code"] = 1,
["Test"] = 3,
["Deploy"] = 4
};
IEnumerable<string> plannedWork = priorities
.Where(workItem => workItem.Value <= 3)
.OrderBy(workItem => workItem.Value)
.Select(workItem => $"{workItem.Key}: {workItem.Value}");
foreach (string item in plannedWork)
{
Console.WriteLine(item);
}
// This example produces the following output:
//
// Code: 1
// Docs: 2
// Test: 3
//
// </CommonOperators>
}
private static void GroupByExample()
{
// <GroupBy>
string[] labels = ["api", "auth", "docs", "deploy"];
IEnumerable<IGrouping<char, string>> groups = labels.GroupBy(label => label[0]);
foreach (IGrouping<char, string> group in groups)
{
Console.WriteLine($"{group.Key}: {string.Join(", ", group)}");
}
// This example produces the following output:
//
// a: api, auth
// d: docs, deploy
//
// </GroupBy>
}
private static void DeferredExecutionExample()
{
// <DeferredExecution>
List<string> workItems = ["design", "docs"];
IEnumerable<string> query = workItems.Where(item => item.StartsWith('d'));
workItems.Add("deploy");
// The query runs here, when foreach asks for the results.
foreach (string item in query)
{
Console.WriteLine(item);
}
// This example produces the following output:
//
// design
// docs
// deploy
//
// </DeferredExecution>
}
private static void ImmediateExecutionExample()
{
// <ImmediateExecution>
List<string> workItems = ["design", "docs"];
IEnumerable<string> query = workItems.Where(item => item.StartsWith('d'));
// Count() reads the matching elements right when this line runs.
int count = query.Count();
Console.WriteLine($"Count before add: {count}");
workItems.Add("deploy");
Console.WriteLine($"Stored count: {count}");
Console.WriteLine($"Current count: {query.Count()}");
// This example produces the following output:
//
// Count before add: 2
// Stored count: 2
// Current count: 3
//
// </ImmediateExecution>
}
private static void ComposeQuerySyntaxExample()
{
// <ComposeQuerySyntax>
(string Title, int Priority, bool IsOpen)[] items =
[
("docs", 2, true),
("tests", 1, true),
("deploy", 3, false),
("api", 1, true)
];
IEnumerable<(string Title, int Priority, bool IsOpen)> openItems =
from item in items
where item.IsOpen
select item;
IEnumerable<string> topOpenItems =
from item in openItems
where item.Priority == 1
orderby item.Title
select item.Title;
foreach (string title in topOpenItems)
{
Console.WriteLine(title);
}
// This example produces the following output:
//
// api
// tests
//
// </ComposeQuerySyntax>
}
private static void ComposeMethodSyntaxExample()
{
// <ComposeMethodSyntax>
(string Title, string Area, bool IsOpen)[] items =
[
("write docs", "docs", true),
("fix tests", "tests", true),
("deploy site", "deploy", false)
];
bool onlyDocs = true;
IEnumerable<(string Title, string Area, bool IsOpen)> query =
items.Where(item => item.IsOpen);
if (onlyDocs)
{
query = query.Where(item => item.Area == "docs");
}
foreach (string title in query.Select(item => item.Title))
{
Console.WriteLine(title); // => write docs
}
// </ComposeMethodSyntax>
}
private static void ComposeWithCachingExample()
{
// <ComposeWithCaching>
List<(string Title, int Priority, bool IsOpen)> items =
[
("docs", 2, true),
("tests", 1, true),
("deploy", 3, false)
];
List<(string Title, int Priority, bool IsOpen)> openItems = items
.Where(item => item.IsOpen)
.ToList();
items.Add(("api", 1, true));
IEnumerable<string> cachedTopOpenItems = openItems
.Where(item => item.Priority == 1)
.OrderBy(item => item.Title)
.Select(item => item.Title);
foreach (string title in cachedTopOpenItems)
{
Console.WriteLine(title); // => tests
}
// </ComposeWithCaching>
}
}The query expression starts with from to name the data source and range variable. The where clause keeps only matching elements, orderby sorts them, and select shapes the result.
LINQ method syntax
Query syntax uses clauses such as from, where, orderby, and select. Method syntax calls LINQ methods directly. For in-memory sequences, the standard LINQ methods are the built-in System.Linq.Enumerable methods for filtering, projection, sorting, grouping, and related operations.
sample · csharpdocs/csharp/fundamentals/statements/snippets/linq-statements/Program.csMethodSyntax
namespace LinqStatements;
public static class Program
{
public static void Main()
{
QuerySyntaxExample();
MethodSyntaxExample();
QuerySyntaxClearerExample();
MethodSyntaxClearerExample();
LambdaExpressionsExample();
QuerySyntaxLambdaExample();
CommonOperatorsExample();
GroupByExample();
DeferredExecutionExample();
ImmediateExecutionExample();
ComposeQuerySyntaxExample();
ComposeMethodSyntaxExample();
ComposeWithCachingExample();
}
private static void QuerySyntaxExample()
{
// <QuerySyntax>
string[] names = ["Ana", "Ben", "Cleo", "Dara"];
IEnumerable<string> query =
from name in names
where name.Length >= 4
orderby name
select name;
foreach (string name in query)
{
Console.WriteLine(name);
}
// This example produces the following output:
//
// Cleo
// Dara
//
// </QuerySyntax>
}
private static void MethodSyntaxExample()
{
// <MethodSyntax>
string[] names = ["Ana", "Ben", "Cleo", "Dara"];
IEnumerable<string> query = names
.Where(name => name.Length >= 4)
.OrderBy(name => name)
.Select(name => name);
foreach (string name in query)
{
Console.WriteLine(name);
}
// This example produces the following output:
//
// Cleo
// Dara
//
// </MethodSyntax>
}
private static void QuerySyntaxClearerExample()
{
// <QuerySyntaxClearer>
(string Area, int Priority)[] workItems =
[
("docs", 2),
("tests", 1),
("deploy", 4),
("api", 1)
];
IEnumerable<string> nextItems =
from item in workItems
let label = $"{item.Area}: P{item.Priority}"
where item.Priority <= 2
orderby item.Priority, item.Area
select label;
foreach (string item in nextItems)
{
Console.WriteLine(item);
}
// This example produces the following output:
//
// api: P1
// tests: P1
// docs: P2
//
// </QuerySyntaxClearer>
}
private static void MethodSyntaxClearerExample()
{
// <MethodSyntaxClearer>
List<string> workItems = ["design", "docs", "deploy", "review"];
int count = workItems.Count(item => item.StartsWith('d'));
Console.WriteLine($"Starts with d: {count}"); // => Starts with d: 3
// </MethodSyntaxClearer>
}
private static void LambdaExpressionsExample()
{
// <LambdaExpressions>
string[] names = ["Ana", "Ben", "Cleo"];
IEnumerable<string> shortNames = names
.Where(name => name.Length == 3)
.Select(name => name.ToUpperInvariant());
foreach (string name in shortNames)
{
Console.WriteLine(name);
}
// This example produces the following output:
//
// ANA
// BEN
//
// </LambdaExpressions>
}
private static void QuerySyntaxLambdaExample()
{
// <QuerySyntaxLambda>
string[] workItems = ["docs", "test", "deploy"];
IEnumerable<string> querySyntax =
from item in workItems
where item.Length == 4
select item;
IEnumerable<string> methodSyntax =
workItems.Where(item => item.Length == 4);
foreach (string item in querySyntax)
{
Console.WriteLine($"Result: {item}");
}
foreach (string item in methodSyntax)
{
Console.WriteLine($"Result: {item}");
}
// This example produces the following output:
//
// Result: docs
// Result: test
// Result: docs
// Result: test
//
// </QuerySyntaxLambda>
}
private static void CommonOperatorsExample()
{
// <CommonOperators>
Dictionary<string, int> priorities = new()
{
["Docs"] = 2,
["Code"] = 1,
["Test"] = 3,
["Deploy"] = 4
};
IEnumerable<string> plannedWork = priorities
.Where(workItem => workItem.Value <= 3)
.OrderBy(workItem => workItem.Value)
.Select(workItem => $"{workItem.Key}: {workItem.Value}");
foreach (string item in plannedWork)
{
Console.WriteLine(item);
}
// This example produces the following output:
//
// Code: 1
// Docs: 2
// Test: 3
//
// </CommonOperators>
}
private static void GroupByExample()
{
// <GroupBy>
string[] labels = ["api", "auth", "docs", "deploy"];
IEnumerable<IGrouping<char, string>> groups = labels.GroupBy(label => label[0]);
foreach (IGrouping<char, string> group in groups)
{
Console.WriteLine($"{group.Key}: {string.Join(", ", group)}");
}
// This example produces the following output:
//
// a: api, auth
// d: docs, deploy
//
// </GroupBy>
}
private static void DeferredExecutionExample()
{
// <DeferredExecution>
List<string> workItems = ["design", "docs"];
IEnumerable<string> query = workItems.Where(item => item.StartsWith('d'));
workItems.Add("deploy");
// The query runs here, when foreach asks for the results.
foreach (string item in query)
{
Console.WriteLine(item);
}
// This example produces the following output:
//
// design
// docs
// deploy
//
// </DeferredExecution>
}
private static void ImmediateExecutionExample()
{
// <ImmediateExecution>
List<string> workItems = ["design", "docs"];
IEnumerable<string> query = workItems.Where(item => item.StartsWith('d'));
// Count() reads the matching elements right when this line runs.
int count = query.Count();
Console.WriteLine($"Count before add: {count}");
workItems.Add("deploy");
Console.WriteLine($"Stored count: {count}");
Console.WriteLine($"Current count: {query.Count()}");
// This example produces the following output:
//
// Count before add: 2
// Stored count: 2
// Current count: 3
//
// </ImmediateExecution>
}
private static void ComposeQuerySyntaxExample()
{
// <ComposeQuerySyntax>
(string Title, int Priority, bool IsOpen)[] items =
[
("docs", 2, true),
("tests", 1, true),
("deploy", 3, false),
("api", 1, true)
];
IEnumerable<(string Title, int Priority, bool IsOpen)> openItems =
from item in items
where item.IsOpen
select item;
IEnumerable<string> topOpenItems =
from item in openItems
where item.Priority == 1
orderby item.Title
select item.Title;
foreach (string title in topOpenItems)
{
Console.WriteLine(title);
}
// This example produces the following output:
//
// api
// tests
//
// </ComposeQuerySyntax>
}
private static void ComposeMethodSyntaxExample()
{
// <ComposeMethodSyntax>
(string Title, string Area, bool IsOpen)[] items =
[
("write docs", "docs", true),
("fix tests", "tests", true),
("deploy site", "deploy", false)
];
bool onlyDocs = true;
IEnumerable<(string Title, string Area, bool IsOpen)> query =
items.Where(item => item.IsOpen);
if (onlyDocs)
{
query = query.Where(item => item.Area == "docs");
}
foreach (string title in query.Select(item => item.Title))
{
Console.WriteLine(title); // => write docs
}
// </ComposeMethodSyntax>
}
private static void ComposeWithCachingExample()
{
// <ComposeWithCaching>
List<(string Title, int Priority, bool IsOpen)> items =
[
("docs", 2, true),
("tests", 1, true),
("deploy", 3, false)
];
List<(string Title, int Priority, bool IsOpen)> openItems = items
.Where(item => item.IsOpen)
.ToList();
items.Add(("api", 1, true));
IEnumerable<string> cachedTopOpenItems = openItems
.Where(item => item.Priority == 1)
.OrderBy(item => item.Title)
.Select(item => item.Title);
foreach (string title in cachedTopOpenItems)
{
Console.WriteLine(title); // => tests
}
// </ComposeWithCaching>
}
}Method syntax is also called fluent syntax because each call returns a result that the next call can use. Many queries can use either form. Use the form that makes the query easiest to read.
Query syntax often reads well when the query has several clauses. The let clause gives a name to an intermediate value before the query filters, sorts, and selects the final result:
sample · csharpdocs/csharp/fundamentals/statements/snippets/linq-statements/Program.csQuerySyntaxClearer
namespace LinqStatements;
public static class Program
{
public static void Main()
{
QuerySyntaxExample();
MethodSyntaxExample();
QuerySyntaxClearerExample();
MethodSyntaxClearerExample();
LambdaExpressionsExample();
QuerySyntaxLambdaExample();
CommonOperatorsExample();
GroupByExample();
DeferredExecutionExample();
ImmediateExecutionExample();
ComposeQuerySyntaxExample();
ComposeMethodSyntaxExample();
ComposeWithCachingExample();
}
private static void QuerySyntaxExample()
{
// <QuerySyntax>
string[] names = ["Ana", "Ben", "Cleo", "Dara"];
IEnumerable<string> query =
from name in names
where name.Length >= 4
orderby name
select name;
foreach (string name in query)
{
Console.WriteLine(name);
}
// This example produces the following output:
//
// Cleo
// Dara
//
// </QuerySyntax>
}
private static void MethodSyntaxExample()
{
// <MethodSyntax>
string[] names = ["Ana", "Ben", "Cleo", "Dara"];
IEnumerable<string> query = names
.Where(name => name.Length >= 4)
.OrderBy(name => name)
.Select(name => name);
foreach (string name in query)
{
Console.WriteLine(name);
}
// This example produces the following output:
//
// Cleo
// Dara
//
// </MethodSyntax>
}
private static void QuerySyntaxClearerExample()
{
// <QuerySyntaxClearer>
(string Area, int Priority)[] workItems =
[
("docs", 2),
("tests", 1),
("deploy", 4),
("api", 1)
];
IEnumerable<string> nextItems =
from item in workItems
let label = $"{item.Area}: P{item.Priority}"
where item.Priority <= 2
orderby item.Priority, item.Area
select label;
foreach (string item in nextItems)
{
Console.WriteLine(item);
}
// This example produces the following output:
//
// api: P1
// tests: P1
// docs: P2
//
// </QuerySyntaxClearer>
}
private static void MethodSyntaxClearerExample()
{
// <MethodSyntaxClearer>
List<string> workItems = ["design", "docs", "deploy", "review"];
int count = workItems.Count(item => item.StartsWith('d'));
Console.WriteLine($"Starts with d: {count}"); // => Starts with d: 3
// </MethodSyntaxClearer>
}
private static void LambdaExpressionsExample()
{
// <LambdaExpressions>
string[] names = ["Ana", "Ben", "Cleo"];
IEnumerable<string> shortNames = names
.Where(name => name.Length == 3)
.Select(name => name.ToUpperInvariant());
foreach (string name in shortNames)
{
Console.WriteLine(name);
}
// This example produces the following output:
//
// ANA
// BEN
//
// </LambdaExpressions>
}
private static void QuerySyntaxLambdaExample()
{
// <QuerySyntaxLambda>
string[] workItems = ["docs", "test", "deploy"];
IEnumerable<string> querySyntax =
from item in workItems
where item.Length == 4
select item;
IEnumerable<string> methodSyntax =
workItems.Where(item => item.Length == 4);
foreach (string item in querySyntax)
{
Console.WriteLine($"Result: {item}");
}
foreach (string item in methodSyntax)
{
Console.WriteLine($"Result: {item}");
}
// This example produces the following output:
//
// Result: docs
// Result: test
// Result: docs
// Result: test
//
// </QuerySyntaxLambda>
}
private static void CommonOperatorsExample()
{
// <CommonOperators>
Dictionary<string, int> priorities = new()
{
["Docs"] = 2,
["Code"] = 1,
["Test"] = 3,
["Deploy"] = 4
};
IEnumerable<string> plannedWork = priorities
.Where(workItem => workItem.Value <= 3)
.OrderBy(workItem => workItem.Value)
.Select(workItem => $"{workItem.Key}: {workItem.Value}");
foreach (string item in plannedWork)
{
Console.WriteLine(item);
}
// This example produces the following output:
//
// Code: 1
// Docs: 2
// Test: 3
//
// </CommonOperators>
}
private static void GroupByExample()
{
// <GroupBy>
string[] labels = ["api", "auth", "docs", "deploy"];
IEnumerable<IGrouping<char, string>> groups = labels.GroupBy(label => label[0]);
foreach (IGrouping<char, string> group in groups)
{
Console.WriteLine($"{group.Key}: {string.Join(", ", group)}");
}
// This example produces the following output:
//
// a: api, auth
// d: docs, deploy
//
// </GroupBy>
}
private static void DeferredExecutionExample()
{
// <DeferredExecution>
List<string> workItems = ["design", "docs"];
IEnumerable<string> query = workItems.Where(item => item.StartsWith('d'));
workItems.Add("deploy");
// The query runs here, when foreach asks for the results.
foreach (string item in query)
{
Console.WriteLine(item);
}
// This example produces the following output:
//
// design
// docs
// deploy
//
// </DeferredExecution>
}
private static void ImmediateExecutionExample()
{
// <ImmediateExecution>
List<string> workItems = ["design", "docs"];
IEnumerable<string> query = workItems.Where(item => item.StartsWith('d'));
// Count() reads the matching elements right when this line runs.
int count = query.Count();
Console.WriteLine($"Count before add: {count}");
workItems.Add("deploy");
Console.WriteLine($"Stored count: {count}");
Console.WriteLine($"Current count: {query.Count()}");
// This example produces the following output:
//
// Count before add: 2
// Stored count: 2
// Current count: 3
//
// </ImmediateExecution>
}
private static void ComposeQuerySyntaxExample()
{
// <ComposeQuerySyntax>
(string Title, int Priority, bool IsOpen)[] items =
[
("docs", 2, true),
("tests", 1, true),
("deploy", 3, false),
("api", 1, true)
];
IEnumerable<(string Title, int Priority, bool IsOpen)> openItems =
from item in items
where item.IsOpen
select item;
IEnumerable<string> topOpenItems =
from item in openItems
where item.Priority == 1
orderby item.Title
select item.Title;
foreach (string title in topOpenItems)
{
Console.WriteLine(title);
}
// This example produces the following output:
//
// api
// tests
//
// </ComposeQuerySyntax>
}
private static void ComposeMethodSyntaxExample()
{
// <ComposeMethodSyntax>
(string Title, string Area, bool IsOpen)[] items =
[
("write docs", "docs", true),
("fix tests", "tests", true),
("deploy site", "deploy", false)
];
bool onlyDocs = true;
IEnumerable<(string Title, string Area, bool IsOpen)> query =
items.Where(item => item.IsOpen);
if (onlyDocs)
{
query = query.Where(item => item.Area == "docs");
}
foreach (string title in query.Select(item => item.Title))
{
Console.WriteLine(title); // => write docs
}
// </ComposeMethodSyntax>
}
private static void ComposeWithCachingExample()
{
// <ComposeWithCaching>
List<(string Title, int Priority, bool IsOpen)> items =
[
("docs", 2, true),
("tests", 1, true),
("deploy", 3, false)
];
List<(string Title, int Priority, bool IsOpen)> openItems = items
.Where(item => item.IsOpen)
.ToList();
items.Add(("api", 1, true));
IEnumerable<string> cachedTopOpenItems = openItems
.Where(item => item.Priority == 1)
.OrderBy(item => item.Title)
.Select(item => item.Title);
foreach (string title in cachedTopOpenItems)
{
Console.WriteLine(title); // => tests
}
// </ComposeWithCaching>
}
}Method syntax often reads well for short operations. It's necessary for methods that don't have query-syntax keyword. For example, System.Linq.Enumerable.Count returns one value directly:
sample · csharpdocs/csharp/fundamentals/statements/snippets/linq-statements/Program.csMethodSyntaxClearer
namespace LinqStatements;
public static class Program
{
public static void Main()
{
QuerySyntaxExample();
MethodSyntaxExample();
QuerySyntaxClearerExample();
MethodSyntaxClearerExample();
LambdaExpressionsExample();
QuerySyntaxLambdaExample();
CommonOperatorsExample();
GroupByExample();
DeferredExecutionExample();
ImmediateExecutionExample();
ComposeQuerySyntaxExample();
ComposeMethodSyntaxExample();
ComposeWithCachingExample();
}
private static void QuerySyntaxExample()
{
// <QuerySyntax>
string[] names = ["Ana", "Ben", "Cleo", "Dara"];
IEnumerable<string> query =
from name in names
where name.Length >= 4
orderby name
select name;
foreach (string name in query)
{
Console.WriteLine(name);
}
// This example produces the following output:
//
// Cleo
// Dara
//
// </QuerySyntax>
}
private static void MethodSyntaxExample()
{
// <MethodSyntax>
string[] names = ["Ana", "Ben", "Cleo", "Dara"];
IEnumerable<string> query = names
.Where(name => name.Length >= 4)
.OrderBy(name => name)
.Select(name => name);
foreach (string name in query)
{
Console.WriteLine(name);
}
// This example produces the following output:
//
// Cleo
// Dara
//
// </MethodSyntax>
}
private static void QuerySyntaxClearerExample()
{
// <QuerySyntaxClearer>
(string Area, int Priority)[] workItems =
[
("docs", 2),
("tests", 1),
("deploy", 4),
("api", 1)
];
IEnumerable<string> nextItems =
from item in workItems
let label = $"{item.Area}: P{item.Priority}"
where item.Priority <= 2
orderby item.Priority, item.Area
select label;
foreach (string item in nextItems)
{
Console.WriteLine(item);
}
// This example produces the following output:
//
// api: P1
// tests: P1
// docs: P2
//
// </QuerySyntaxClearer>
}
private static void MethodSyntaxClearerExample()
{
// <MethodSyntaxClearer>
List<string> workItems = ["design", "docs", "deploy", "review"];
int count = workItems.Count(item => item.StartsWith('d'));
Console.WriteLine($"Starts with d: {count}"); // => Starts with d: 3
// </MethodSyntaxClearer>
}
private static void LambdaExpressionsExample()
{
// <LambdaExpressions>
string[] names = ["Ana", "Ben", "Cleo"];
IEnumerable<string> shortNames = names
.Where(name => name.Length == 3)
.Select(name => name.ToUpperInvariant());
foreach (string name in shortNames)
{
Console.WriteLine(name);
}
// This example produces the following output:
//
// ANA
// BEN
//
// </LambdaExpressions>
}
private static void QuerySyntaxLambdaExample()
{
// <QuerySyntaxLambda>
string[] workItems = ["docs", "test", "deploy"];
IEnumerable<string> querySyntax =
from item in workItems
where item.Length == 4
select item;
IEnumerable<string> methodSyntax =
workItems.Where(item => item.Length == 4);
foreach (string item in querySyntax)
{
Console.WriteLine($"Result: {item}");
}
foreach (string item in methodSyntax)
{
Console.WriteLine($"Result: {item}");
}
// This example produces the following output:
//
// Result: docs
// Result: test
// Result: docs
// Result: test
//
// </QuerySyntaxLambda>
}
private static void CommonOperatorsExample()
{
// <CommonOperators>
Dictionary<string, int> priorities = new()
{
["Docs"] = 2,
["Code"] = 1,
["Test"] = 3,
["Deploy"] = 4
};
IEnumerable<string> plannedWork = priorities
.Where(workItem => workItem.Value <= 3)
.OrderBy(workItem => workItem.Value)
.Select(workItem => $"{workItem.Key}: {workItem.Value}");
foreach (string item in plannedWork)
{
Console.WriteLine(item);
}
// This example produces the following output:
//
// Code: 1
// Docs: 2
// Test: 3
//
// </CommonOperators>
}
private static void GroupByExample()
{
// <GroupBy>
string[] labels = ["api", "auth", "docs", "deploy"];
IEnumerable<IGrouping<char, string>> groups = labels.GroupBy(label => label[0]);
foreach (IGrouping<char, string> group in groups)
{
Console.WriteLine($"{group.Key}: {string.Join(", ", group)}");
}
// This example produces the following output:
//
// a: api, auth
// d: docs, deploy
//
// </GroupBy>
}
private static void DeferredExecutionExample()
{
// <DeferredExecution>
List<string> workItems = ["design", "docs"];
IEnumerable<string> query = workItems.Where(item => item.StartsWith('d'));
workItems.Add("deploy");
// The query runs here, when foreach asks for the results.
foreach (string item in query)
{
Console.WriteLine(item);
}
// This example produces the following output:
//
// design
// docs
// deploy
//
// </DeferredExecution>
}
private static void ImmediateExecutionExample()
{
// <ImmediateExecution>
List<string> workItems = ["design", "docs"];
IEnumerable<string> query = workItems.Where(item => item.StartsWith('d'));
// Count() reads the matching elements right when this line runs.
int count = query.Count();
Console.WriteLine($"Count before add: {count}");
workItems.Add("deploy");
Console.WriteLine($"Stored count: {count}");
Console.WriteLine($"Current count: {query.Count()}");
// This example produces the following output:
//
// Count before add: 2
// Stored count: 2
// Current count: 3
//
// </ImmediateExecution>
}
private static void ComposeQuerySyntaxExample()
{
// <ComposeQuerySyntax>
(string Title, int Priority, bool IsOpen)[] items =
[
("docs", 2, true),
("tests", 1, true),
("deploy", 3, false),
("api", 1, true)
];
IEnumerable<(string Title, int Priority, bool IsOpen)> openItems =
from item in items
where item.IsOpen
select item;
IEnumerable<string> topOpenItems =
from item in openItems
where item.Priority == 1
orderby item.Title
select item.Title;
foreach (string title in topOpenItems)
{
Console.WriteLine(title);
}
// This example produces the following output:
//
// api
// tests
//
// </ComposeQuerySyntax>
}
private static void ComposeMethodSyntaxExample()
{
// <ComposeMethodSyntax>
(string Title, string Area, bool IsOpen)[] items =
[
("write docs", "docs", true),
("fix tests", "tests", true),
("deploy site", "deploy", false)
];
bool onlyDocs = true;
IEnumerable<(string Title, string Area, bool IsOpen)> query =
items.Where(item => item.IsOpen);
if (onlyDocs)
{
query = query.Where(item => item.Area == "docs");
}
foreach (string title in query.Select(item => item.Title))
{
Console.WriteLine(title); // => write docs
}
// </ComposeMethodSyntax>
}
private static void ComposeWithCachingExample()
{
// <ComposeWithCaching>
List<(string Title, int Priority, bool IsOpen)> items =
[
("docs", 2, true),
("tests", 1, true),
("deploy", 3, false)
];
List<(string Title, int Priority, bool IsOpen)> openItems = items
.Where(item => item.IsOpen)
.ToList();
items.Add(("api", 1, true));
IEnumerable<string> cachedTopOpenItems = openItems
.Where(item => item.Priority == 1)
.OrderBy(item => item.Title)
.Select(item => item.Title);
foreach (string title in cachedTopOpenItems)
{
Console.WriteLine(title); // => tests
}
// </ComposeWithCaching>
}
}Lambda expressions and LINQ
A lambda expression is an anonymous function that you can pass as an argument. LINQ method syntax commonly uses lambda expressions to say what each operator should do with each element.
sample · csharpdocs/csharp/fundamentals/statements/snippets/linq-statements/Program.csLambdaExpressions
namespace LinqStatements;
public static class Program
{
public static void Main()
{
QuerySyntaxExample();
MethodSyntaxExample();
QuerySyntaxClearerExample();
MethodSyntaxClearerExample();
LambdaExpressionsExample();
QuerySyntaxLambdaExample();
CommonOperatorsExample();
GroupByExample();
DeferredExecutionExample();
ImmediateExecutionExample();
ComposeQuerySyntaxExample();
ComposeMethodSyntaxExample();
ComposeWithCachingExample();
}
private static void QuerySyntaxExample()
{
// <QuerySyntax>
string[] names = ["Ana", "Ben", "Cleo", "Dara"];
IEnumerable<string> query =
from name in names
where name.Length >= 4
orderby name
select name;
foreach (string name in query)
{
Console.WriteLine(name);
}
// This example produces the following output:
//
// Cleo
// Dara
//
// </QuerySyntax>
}
private static void MethodSyntaxExample()
{
// <MethodSyntax>
string[] names = ["Ana", "Ben", "Cleo", "Dara"];
IEnumerable<string> query = names
.Where(name => name.Length >= 4)
.OrderBy(name => name)
.Select(name => name);
foreach (string name in query)
{
Console.WriteLine(name);
}
// This example produces the following output:
//
// Cleo
// Dara
//
// </MethodSyntax>
}
private static void QuerySyntaxClearerExample()
{
// <QuerySyntaxClearer>
(string Area, int Priority)[] workItems =
[
("docs", 2),
("tests", 1),
("deploy", 4),
("api", 1)
];
IEnumerable<string> nextItems =
from item in workItems
let label = $"{item.Area}: P{item.Priority}"
where item.Priority <= 2
orderby item.Priority, item.Area
select label;
foreach (string item in nextItems)
{
Console.WriteLine(item);
}
// This example produces the following output:
//
// api: P1
// tests: P1
// docs: P2
//
// </QuerySyntaxClearer>
}
private static void MethodSyntaxClearerExample()
{
// <MethodSyntaxClearer>
List<string> workItems = ["design", "docs", "deploy", "review"];
int count = workItems.Count(item => item.StartsWith('d'));
Console.WriteLine($"Starts with d: {count}"); // => Starts with d: 3
// </MethodSyntaxClearer>
}
private static void LambdaExpressionsExample()
{
// <LambdaExpressions>
string[] names = ["Ana", "Ben", "Cleo"];
IEnumerable<string> shortNames = names
.Where(name => name.Length == 3)
.Select(name => name.ToUpperInvariant());
foreach (string name in shortNames)
{
Console.WriteLine(name);
}
// This example produces the following output:
//
// ANA
// BEN
//
// </LambdaExpressions>
}
private static void QuerySyntaxLambdaExample()
{
// <QuerySyntaxLambda>
string[] workItems = ["docs", "test", "deploy"];
IEnumerable<string> querySyntax =
from item in workItems
where item.Length == 4
select item;
IEnumerable<string> methodSyntax =
workItems.Where(item => item.Length == 4);
foreach (string item in querySyntax)
{
Console.WriteLine($"Result: {item}");
}
foreach (string item in methodSyntax)
{
Console.WriteLine($"Result: {item}");
}
// This example produces the following output:
//
// Result: docs
// Result: test
// Result: docs
// Result: test
//
// </QuerySyntaxLambda>
}
private static void CommonOperatorsExample()
{
// <CommonOperators>
Dictionary<string, int> priorities = new()
{
["Docs"] = 2,
["Code"] = 1,
["Test"] = 3,
["Deploy"] = 4
};
IEnumerable<string> plannedWork = priorities
.Where(workItem => workItem.Value <= 3)
.OrderBy(workItem => workItem.Value)
.Select(workItem => $"{workItem.Key}: {workItem.Value}");
foreach (string item in plannedWork)
{
Console.WriteLine(item);
}
// This example produces the following output:
//
// Code: 1
// Docs: 2
// Test: 3
//
// </CommonOperators>
}
private static void GroupByExample()
{
// <GroupBy>
string[] labels = ["api", "auth", "docs", "deploy"];
IEnumerable<IGrouping<char, string>> groups = labels.GroupBy(label => label[0]);
foreach (IGrouping<char, string> group in groups)
{
Console.WriteLine($"{group.Key}: {string.Join(", ", group)}");
}
// This example produces the following output:
//
// a: api, auth
// d: docs, deploy
//
// </GroupBy>
}
private static void DeferredExecutionExample()
{
// <DeferredExecution>
List<string> workItems = ["design", "docs"];
IEnumerable<string> query = workItems.Where(item => item.StartsWith('d'));
workItems.Add("deploy");
// The query runs here, when foreach asks for the results.
foreach (string item in query)
{
Console.WriteLine(item);
}
// This example produces the following output:
//
// design
// docs
// deploy
//
// </DeferredExecution>
}
private static void ImmediateExecutionExample()
{
// <ImmediateExecution>
List<string> workItems = ["design", "docs"];
IEnumerable<string> query = workItems.Where(item => item.StartsWith('d'));
// Count() reads the matching elements right when this line runs.
int count = query.Count();
Console.WriteLine($"Count before add: {count}");
workItems.Add("deploy");
Console.WriteLine($"Stored count: {count}");
Console.WriteLine($"Current count: {query.Count()}");
// This example produces the following output:
//
// Count before add: 2
// Stored count: 2
// Current count: 3
//
// </ImmediateExecution>
}
private static void ComposeQuerySyntaxExample()
{
// <ComposeQuerySyntax>
(string Title, int Priority, bool IsOpen)[] items =
[
("docs", 2, true),
("tests", 1, true),
("deploy", 3, false),
("api", 1, true)
];
IEnumerable<(string Title, int Priority, bool IsOpen)> openItems =
from item in items
where item.IsOpen
select item;
IEnumerable<string> topOpenItems =
from item in openItems
where item.Priority == 1
orderby item.Title
select item.Title;
foreach (string title in topOpenItems)
{
Console.WriteLine(title);
}
// This example produces the following output:
//
// api
// tests
//
// </ComposeQuerySyntax>
}
private static void ComposeMethodSyntaxExample()
{
// <ComposeMethodSyntax>
(string Title, string Area, bool IsOpen)[] items =
[
("write docs", "docs", true),
("fix tests", "tests", true),
("deploy site", "deploy", false)
];
bool onlyDocs = true;
IEnumerable<(string Title, string Area, bool IsOpen)> query =
items.Where(item => item.IsOpen);
if (onlyDocs)
{
query = query.Where(item => item.Area == "docs");
}
foreach (string title in query.Select(item => item.Title))
{
Console.WriteLine(title); // => write docs
}
// </ComposeMethodSyntax>
}
private static void ComposeWithCachingExample()
{
// <ComposeWithCaching>
List<(string Title, int Priority, bool IsOpen)> items =
[
("docs", 2, true),
("tests", 1, true),
("deploy", 3, false)
];
List<(string Title, int Priority, bool IsOpen)> openItems = items
.Where(item => item.IsOpen)
.ToList();
items.Add(("api", 1, true));
IEnumerable<string> cachedTopOpenItems = openItems
.Where(item => item.Priority == 1)
.OrderBy(item => item.Title)
.Select(item => item.Title);
foreach (string title in cachedTopOpenItems)
{
Console.WriteLine(title); // => tests
}
// </ComposeWithCaching>
}
}In name => name.Length == 3, name is the input element and name.Length == 3 is the Boolean expression that decides whether the element belongs in the result. For more information about lambda expressions and delegate types, see Lambda expressions, delegates, and events in the fundamentals.
Query-syntax clauses use lambda expressions too. Clauses such as where, orderby, and select compile to method calls that take lambda expressions. The range variable becomes the lambda parameter, and the clause expression becomes the lambda body. Query syntax is a concise way to write those same lambdas:
sample · csharpdocs/csharp/fundamentals/statements/snippets/linq-statements/Program.csQuerySyntaxLambda
namespace LinqStatements;
public static class Program
{
public static void Main()
{
QuerySyntaxExample();
MethodSyntaxExample();
QuerySyntaxClearerExample();
MethodSyntaxClearerExample();
LambdaExpressionsExample();
QuerySyntaxLambdaExample();
CommonOperatorsExample();
GroupByExample();
DeferredExecutionExample();
ImmediateExecutionExample();
ComposeQuerySyntaxExample();
ComposeMethodSyntaxExample();
ComposeWithCachingExample();
}
private static void QuerySyntaxExample()
{
// <QuerySyntax>
string[] names = ["Ana", "Ben", "Cleo", "Dara"];
IEnumerable<string> query =
from name in names
where name.Length >= 4
orderby name
select name;
foreach (string name in query)
{
Console.WriteLine(name);
}
// This example produces the following output:
//
// Cleo
// Dara
//
// </QuerySyntax>
}
private static void MethodSyntaxExample()
{
// <MethodSyntax>
string[] names = ["Ana", "Ben", "Cleo", "Dara"];
IEnumerable<string> query = names
.Where(name => name.Length >= 4)
.OrderBy(name => name)
.Select(name => name);
foreach (string name in query)
{
Console.WriteLine(name);
}
// This example produces the following output:
//
// Cleo
// Dara
//
// </MethodSyntax>
}
private static void QuerySyntaxClearerExample()
{
// <QuerySyntaxClearer>
(string Area, int Priority)[] workItems =
[
("docs", 2),
("tests", 1),
("deploy", 4),
("api", 1)
];
IEnumerable<string> nextItems =
from item in workItems
let label = $"{item.Area}: P{item.Priority}"
where item.Priority <= 2
orderby item.Priority, item.Area
select label;
foreach (string item in nextItems)
{
Console.WriteLine(item);
}
// This example produces the following output:
//
// api: P1
// tests: P1
// docs: P2
//
// </QuerySyntaxClearer>
}
private static void MethodSyntaxClearerExample()
{
// <MethodSyntaxClearer>
List<string> workItems = ["design", "docs", "deploy", "review"];
int count = workItems.Count(item => item.StartsWith('d'));
Console.WriteLine($"Starts with d: {count}"); // => Starts with d: 3
// </MethodSyntaxClearer>
}
private static void LambdaExpressionsExample()
{
// <LambdaExpressions>
string[] names = ["Ana", "Ben", "Cleo"];
IEnumerable<string> shortNames = names
.Where(name => name.Length == 3)
.Select(name => name.ToUpperInvariant());
foreach (string name in shortNames)
{
Console.WriteLine(name);
}
// This example produces the following output:
//
// ANA
// BEN
//
// </LambdaExpressions>
}
private static void QuerySyntaxLambdaExample()
{
// <QuerySyntaxLambda>
string[] workItems = ["docs", "test", "deploy"];
IEnumerable<string> querySyntax =
from item in workItems
where item.Length == 4
select item;
IEnumerable<string> methodSyntax =
workItems.Where(item => item.Length == 4);
foreach (string item in querySyntax)
{
Console.WriteLine($"Result: {item}");
}
foreach (string item in methodSyntax)
{
Console.WriteLine($"Result: {item}");
}
// This example produces the following output:
//
// Result: docs
// Result: test
// Result: docs
// Result: test
//
// </QuerySyntaxLambda>
}
private static void CommonOperatorsExample()
{
// <CommonOperators>
Dictionary<string, int> priorities = new()
{
["Docs"] = 2,
["Code"] = 1,
["Test"] = 3,
["Deploy"] = 4
};
IEnumerable<string> plannedWork = priorities
.Where(workItem => workItem.Value <= 3)
.OrderBy(workItem => workItem.Value)
.Select(workItem => $"{workItem.Key}: {workItem.Value}");
foreach (string item in plannedWork)
{
Console.WriteLine(item);
}
// This example produces the following output:
//
// Code: 1
// Docs: 2
// Test: 3
//
// </CommonOperators>
}
private static void GroupByExample()
{
// <GroupBy>
string[] labels = ["api", "auth", "docs", "deploy"];
IEnumerable<IGrouping<char, string>> groups = labels.GroupBy(label => label[0]);
foreach (IGrouping<char, string> group in groups)
{
Console.WriteLine($"{group.Key}: {string.Join(", ", group)}");
}
// This example produces the following output:
//
// a: api, auth
// d: docs, deploy
//
// </GroupBy>
}
private static void DeferredExecutionExample()
{
// <DeferredExecution>
List<string> workItems = ["design", "docs"];
IEnumerable<string> query = workItems.Where(item => item.StartsWith('d'));
workItems.Add("deploy");
// The query runs here, when foreach asks for the results.
foreach (string item in query)
{
Console.WriteLine(item);
}
// This example produces the following output:
//
// design
// docs
// deploy
//
// </DeferredExecution>
}
private static void ImmediateExecutionExample()
{
// <ImmediateExecution>
List<string> workItems = ["design", "docs"];
IEnumerable<string> query = workItems.Where(item => item.StartsWith('d'));
// Count() reads the matching elements right when this line runs.
int count = query.Count();
Console.WriteLine($"Count before add: {count}");
workItems.Add("deploy");
Console.WriteLine($"Stored count: {count}");
Console.WriteLine($"Current count: {query.Count()}");
// This example produces the following output:
//
// Count before add: 2
// Stored count: 2
// Current count: 3
//
// </ImmediateExecution>
}
private static void ComposeQuerySyntaxExample()
{
// <ComposeQuerySyntax>
(string Title, int Priority, bool IsOpen)[] items =
[
("docs", 2, true),
("tests", 1, true),
("deploy", 3, false),
("api", 1, true)
];
IEnumerable<(string Title, int Priority, bool IsOpen)> openItems =
from item in items
where item.IsOpen
select item;
IEnumerable<string> topOpenItems =
from item in openItems
where item.Priority == 1
orderby item.Title
select item.Title;
foreach (string title in topOpenItems)
{
Console.WriteLine(title);
}
// This example produces the following output:
//
// api
// tests
//
// </ComposeQuerySyntax>
}
private static void ComposeMethodSyntaxExample()
{
// <ComposeMethodSyntax>
(string Title, string Area, bool IsOpen)[] items =
[
("write docs", "docs", true),
("fix tests", "tests", true),
("deploy site", "deploy", false)
];
bool onlyDocs = true;
IEnumerable<(string Title, string Area, bool IsOpen)> query =
items.Where(item => item.IsOpen);
if (onlyDocs)
{
query = query.Where(item => item.Area == "docs");
}
foreach (string title in query.Select(item => item.Title))
{
Console.WriteLine(title); // => write docs
}
// </ComposeMethodSyntax>
}
private static void ComposeWithCachingExample()
{
// <ComposeWithCaching>
List<(string Title, int Priority, bool IsOpen)> items =
[
("docs", 2, true),
("tests", 1, true),
("deploy", 3, false)
];
List<(string Title, int Priority, bool IsOpen)> openItems = items
.Where(item => item.IsOpen)
.ToList();
items.Add(("api", 1, true));
IEnumerable<string> cachedTopOpenItems = openItems
.Where(item => item.Priority == 1)
.OrderBy(item => item.Title)
.Select(item => item.Title);
foreach (string title in cachedTopOpenItems)
{
Console.WriteLine(title); // => tests
}
// </ComposeWithCaching>
}
}Common LINQ methods
The most common LINQ methods cover the everyday steps of a query: filter data, shape results, sort, group, and summarize. These methods are in the System.Linq namespace and work with sequences such as System.Collections.Generic.IEnumerable.
- System.Linq.Enumerable.Where keeps only the elements that match a condition.
- System.Linq.Enumerable.Select transforms each element into a new value. C# calls this operation a projection.
- System.Linq.Enumerable.OrderBy sorts elements.
- System.Linq.Enumerable.GroupBy creates groups of elements that share a key.
- Aggregation methods such as System.Linq.Enumerable.Sum, System.Linq.Enumerable.Count, and System.Linq.Enumerable.Aggregate produce a single value from all elements in the data source.
sample · csharpdocs/csharp/fundamentals/statements/snippets/linq-statements/Program.csCommonOperators
namespace LinqStatements;
public static class Program
{
public static void Main()
{
QuerySyntaxExample();
MethodSyntaxExample();
QuerySyntaxClearerExample();
MethodSyntaxClearerExample();
LambdaExpressionsExample();
QuerySyntaxLambdaExample();
CommonOperatorsExample();
GroupByExample();
DeferredExecutionExample();
ImmediateExecutionExample();
ComposeQuerySyntaxExample();
ComposeMethodSyntaxExample();
ComposeWithCachingExample();
}
private static void QuerySyntaxExample()
{
// <QuerySyntax>
string[] names = ["Ana", "Ben", "Cleo", "Dara"];
IEnumerable<string> query =
from name in names
where name.Length >= 4
orderby name
select name;
foreach (string name in query)
{
Console.WriteLine(name);
}
// This example produces the following output:
//
// Cleo
// Dara
//
// </QuerySyntax>
}
private static void MethodSyntaxExample()
{
// <MethodSyntax>
string[] names = ["Ana", "Ben", "Cleo", "Dara"];
IEnumerable<string> query = names
.Where(name => name.Length >= 4)
.OrderBy(name => name)
.Select(name => name);
foreach (string name in query)
{
Console.WriteLine(name);
}
// This example produces the following output:
//
// Cleo
// Dara
//
// </MethodSyntax>
}
private static void QuerySyntaxClearerExample()
{
// <QuerySyntaxClearer>
(string Area, int Priority)[] workItems =
[
("docs", 2),
("tests", 1),
("deploy", 4),
("api", 1)
];
IEnumerable<string> nextItems =
from item in workItems
let label = $"{item.Area}: P{item.Priority}"
where item.Priority <= 2
orderby item.Priority, item.Area
select label;
foreach (string item in nextItems)
{
Console.WriteLine(item);
}
// This example produces the following output:
//
// api: P1
// tests: P1
// docs: P2
//
// </QuerySyntaxClearer>
}
private static void MethodSyntaxClearerExample()
{
// <MethodSyntaxClearer>
List<string> workItems = ["design", "docs", "deploy", "review"];
int count = workItems.Count(item => item.StartsWith('d'));
Console.WriteLine($"Starts with d: {count}"); // => Starts with d: 3
// </MethodSyntaxClearer>
}
private static void LambdaExpressionsExample()
{
// <LambdaExpressions>
string[] names = ["Ana", "Ben", "Cleo"];
IEnumerable<string> shortNames = names
.Where(name => name.Length == 3)
.Select(name => name.ToUpperInvariant());
foreach (string name in shortNames)
{
Console.WriteLine(name);
}
// This example produces the following output:
//
// ANA
// BEN
//
// </LambdaExpressions>
}
private static void QuerySyntaxLambdaExample()
{
// <QuerySyntaxLambda>
string[] workItems = ["docs", "test", "deploy"];
IEnumerable<string> querySyntax =
from item in workItems
where item.Length == 4
select item;
IEnumerable<string> methodSyntax =
workItems.Where(item => item.Length == 4);
foreach (string item in querySyntax)
{
Console.WriteLine($"Result: {item}");
}
foreach (string item in methodSyntax)
{
Console.WriteLine($"Result: {item}");
}
// This example produces the following output:
//
// Result: docs
// Result: test
// Result: docs
// Result: test
//
// </QuerySyntaxLambda>
}
private static void CommonOperatorsExample()
{
// <CommonOperators>
Dictionary<string, int> priorities = new()
{
["Docs"] = 2,
["Code"] = 1,
["Test"] = 3,
["Deploy"] = 4
};
IEnumerable<string> plannedWork = priorities
.Where(workItem => workItem.Value <= 3)
.OrderBy(workItem => workItem.Value)
.Select(workItem => $"{workItem.Key}: {workItem.Value}");
foreach (string item in plannedWork)
{
Console.WriteLine(item);
}
// This example produces the following output:
//
// Code: 1
// Docs: 2
// Test: 3
//
// </CommonOperators>
}
private static void GroupByExample()
{
// <GroupBy>
string[] labels = ["api", "auth", "docs", "deploy"];
IEnumerable<IGrouping<char, string>> groups = labels.GroupBy(label => label[0]);
foreach (IGrouping<char, string> group in groups)
{
Console.WriteLine($"{group.Key}: {string.Join(", ", group)}");
}
// This example produces the following output:
//
// a: api, auth
// d: docs, deploy
//
// </GroupBy>
}
private static void DeferredExecutionExample()
{
// <DeferredExecution>
List<string> workItems = ["design", "docs"];
IEnumerable<string> query = workItems.Where(item => item.StartsWith('d'));
workItems.Add("deploy");
// The query runs here, when foreach asks for the results.
foreach (string item in query)
{
Console.WriteLine(item);
}
// This example produces the following output:
//
// design
// docs
// deploy
//
// </DeferredExecution>
}
private static void ImmediateExecutionExample()
{
// <ImmediateExecution>
List<string> workItems = ["design", "docs"];
IEnumerable<string> query = workItems.Where(item => item.StartsWith('d'));
// Count() reads the matching elements right when this line runs.
int count = query.Count();
Console.WriteLine($"Count before add: {count}");
workItems.Add("deploy");
Console.WriteLine($"Stored count: {count}");
Console.WriteLine($"Current count: {query.Count()}");
// This example produces the following output:
//
// Count before add: 2
// Stored count: 2
// Current count: 3
//
// </ImmediateExecution>
}
private static void ComposeQuerySyntaxExample()
{
// <ComposeQuerySyntax>
(string Title, int Priority, bool IsOpen)[] items =
[
("docs", 2, true),
("tests", 1, true),
("deploy", 3, false),
("api", 1, true)
];
IEnumerable<(string Title, int Priority, bool IsOpen)> openItems =
from item in items
where item.IsOpen
select item;
IEnumerable<string> topOpenItems =
from item in openItems
where item.Priority == 1
orderby item.Title
select item.Title;
foreach (string title in topOpenItems)
{
Console.WriteLine(title);
}
// This example produces the following output:
//
// api
// tests
//
// </ComposeQuerySyntax>
}
private static void ComposeMethodSyntaxExample()
{
// <ComposeMethodSyntax>
(string Title, string Area, bool IsOpen)[] items =
[
("write docs", "docs", true),
("fix tests", "tests", true),
("deploy site", "deploy", false)
];
bool onlyDocs = true;
IEnumerable<(string Title, string Area, bool IsOpen)> query =
items.Where(item => item.IsOpen);
if (onlyDocs)
{
query = query.Where(item => item.Area == "docs");
}
foreach (string title in query.Select(item => item.Title))
{
Console.WriteLine(title); // => write docs
}
// </ComposeMethodSyntax>
}
private static void ComposeWithCachingExample()
{
// <ComposeWithCaching>
List<(string Title, int Priority, bool IsOpen)> items =
[
("docs", 2, true),
("tests", 1, true),
("deploy", 3, false)
];
List<(string Title, int Priority, bool IsOpen)> openItems = items
.Where(item => item.IsOpen)
.ToList();
items.Add(("api", 1, true));
IEnumerable<string> cachedTopOpenItems = openItems
.Where(item => item.Priority == 1)
.OrderBy(item => item.Title)
.Select(item => item.Title);
foreach (string title in cachedTopOpenItems)
{
Console.WriteLine(title); // => tests
}
// </ComposeWithCaching>
}
}A projection creates a result value from each input element. In the previous example, the projection creates strings that combine a work item name and its priority.
Group related values
Use System.Linq.Enumerable.GroupBy when the result should contain groups of elements that share a key. Each group is represented by System.Linq.IGrouping, which exposes the group key and the elements in that group.
sample · csharpdocs/csharp/fundamentals/statements/snippets/linq-statements/Program.csGroupBy
namespace LinqStatements;
public static class Program
{
public static void Main()
{
QuerySyntaxExample();
MethodSyntaxExample();
QuerySyntaxClearerExample();
MethodSyntaxClearerExample();
LambdaExpressionsExample();
QuerySyntaxLambdaExample();
CommonOperatorsExample();
GroupByExample();
DeferredExecutionExample();
ImmediateExecutionExample();
ComposeQuerySyntaxExample();
ComposeMethodSyntaxExample();
ComposeWithCachingExample();
}
private static void QuerySyntaxExample()
{
// <QuerySyntax>
string[] names = ["Ana", "Ben", "Cleo", "Dara"];
IEnumerable<string> query =
from name in names
where name.Length >= 4
orderby name
select name;
foreach (string name in query)
{
Console.WriteLine(name);
}
// This example produces the following output:
//
// Cleo
// Dara
//
// </QuerySyntax>
}
private static void MethodSyntaxExample()
{
// <MethodSyntax>
string[] names = ["Ana", "Ben", "Cleo", "Dara"];
IEnumerable<string> query = names
.Where(name => name.Length >= 4)
.OrderBy(name => name)
.Select(name => name);
foreach (string name in query)
{
Console.WriteLine(name);
}
// This example produces the following output:
//
// Cleo
// Dara
//
// </MethodSyntax>
}
private static void QuerySyntaxClearerExample()
{
// <QuerySyntaxClearer>
(string Area, int Priority)[] workItems =
[
("docs", 2),
("tests", 1),
("deploy", 4),
("api", 1)
];
IEnumerable<string> nextItems =
from item in workItems
let label = $"{item.Area}: P{item.Priority}"
where item.Priority <= 2
orderby item.Priority, item.Area
select label;
foreach (string item in nextItems)
{
Console.WriteLine(item);
}
// This example produces the following output:
//
// api: P1
// tests: P1
// docs: P2
//
// </QuerySyntaxClearer>
}
private static void MethodSyntaxClearerExample()
{
// <MethodSyntaxClearer>
List<string> workItems = ["design", "docs", "deploy", "review"];
int count = workItems.Count(item => item.StartsWith('d'));
Console.WriteLine($"Starts with d: {count}"); // => Starts with d: 3
// </MethodSyntaxClearer>
}
private static void LambdaExpressionsExample()
{
// <LambdaExpressions>
string[] names = ["Ana", "Ben", "Cleo"];
IEnumerable<string> shortNames = names
.Where(name => name.Length == 3)
.Select(name => name.ToUpperInvariant());
foreach (string name in shortNames)
{
Console.WriteLine(name);
}
// This example produces the following output:
//
// ANA
// BEN
//
// </LambdaExpressions>
}
private static void QuerySyntaxLambdaExample()
{
// <QuerySyntaxLambda>
string[] workItems = ["docs", "test", "deploy"];
IEnumerable<string> querySyntax =
from item in workItems
where item.Length == 4
select item;
IEnumerable<string> methodSyntax =
workItems.Where(item => item.Length == 4);
foreach (string item in querySyntax)
{
Console.WriteLine($"Result: {item}");
}
foreach (string item in methodSyntax)
{
Console.WriteLine($"Result: {item}");
}
// This example produces the following output:
//
// Result: docs
// Result: test
// Result: docs
// Result: test
//
// </QuerySyntaxLambda>
}
private static void CommonOperatorsExample()
{
// <CommonOperators>
Dictionary<string, int> priorities = new()
{
["Docs"] = 2,
["Code"] = 1,
["Test"] = 3,
["Deploy"] = 4
};
IEnumerable<string> plannedWork = priorities
.Where(workItem => workItem.Value <= 3)
.OrderBy(workItem => workItem.Value)
.Select(workItem => $"{workItem.Key}: {workItem.Value}");
foreach (string item in plannedWork)
{
Console.WriteLine(item);
}
// This example produces the following output:
//
// Code: 1
// Docs: 2
// Test: 3
//
// </CommonOperators>
}
private static void GroupByExample()
{
// <GroupBy>
string[] labels = ["api", "auth", "docs", "deploy"];
IEnumerable<IGrouping<char, string>> groups = labels.GroupBy(label => label[0]);
foreach (IGrouping<char, string> group in groups)
{
Console.WriteLine($"{group.Key}: {string.Join(", ", group)}");
}
// This example produces the following output:
//
// a: api, auth
// d: docs, deploy
//
// </GroupBy>
}
private static void DeferredExecutionExample()
{
// <DeferredExecution>
List<string> workItems = ["design", "docs"];
IEnumerable<string> query = workItems.Where(item => item.StartsWith('d'));
workItems.Add("deploy");
// The query runs here, when foreach asks for the results.
foreach (string item in query)
{
Console.WriteLine(item);
}
// This example produces the following output:
//
// design
// docs
// deploy
//
// </DeferredExecution>
}
private static void ImmediateExecutionExample()
{
// <ImmediateExecution>
List<string> workItems = ["design", "docs"];
IEnumerable<string> query = workItems.Where(item => item.StartsWith('d'));
// Count() reads the matching elements right when this line runs.
int count = query.Count();
Console.WriteLine($"Count before add: {count}");
workItems.Add("deploy");
Console.WriteLine($"Stored count: {count}");
Console.WriteLine($"Current count: {query.Count()}");
// This example produces the following output:
//
// Count before add: 2
// Stored count: 2
// Current count: 3
//
// </ImmediateExecution>
}
private static void ComposeQuerySyntaxExample()
{
// <ComposeQuerySyntax>
(string Title, int Priority, bool IsOpen)[] items =
[
("docs", 2, true),
("tests", 1, true),
("deploy", 3, false),
("api", 1, true)
];
IEnumerable<(string Title, int Priority, bool IsOpen)> openItems =
from item in items
where item.IsOpen
select item;
IEnumerable<string> topOpenItems =
from item in openItems
where item.Priority == 1
orderby item.Title
select item.Title;
foreach (string title in topOpenItems)
{
Console.WriteLine(title);
}
// This example produces the following output:
//
// api
// tests
//
// </ComposeQuerySyntax>
}
private static void ComposeMethodSyntaxExample()
{
// <ComposeMethodSyntax>
(string Title, string Area, bool IsOpen)[] items =
[
("write docs", "docs", true),
("fix tests", "tests", true),
("deploy site", "deploy", false)
];
bool onlyDocs = true;
IEnumerable<(string Title, string Area, bool IsOpen)> query =
items.Where(item => item.IsOpen);
if (onlyDocs)
{
query = query.Where(item => item.Area == "docs");
}
foreach (string title in query.Select(item => item.Title))
{
Console.WriteLine(title); // => write docs
}
// </ComposeMethodSyntax>
}
private static void ComposeWithCachingExample()
{
// <ComposeWithCaching>
List<(string Title, int Priority, bool IsOpen)> items =
[
("docs", 2, true),
("tests", 1, true),
("deploy", 3, false)
];
List<(string Title, int Priority, bool IsOpen)> openItems = items
.Where(item => item.IsOpen)
.ToList();
items.Add(("api", 1, true));
IEnumerable<string> cachedTopOpenItems = openItems
.Where(item => item.Priority == 1)
.OrderBy(item => item.Title)
.Select(item => item.Title);
foreach (string title in cachedTopOpenItems)
{
Console.WriteLine(title); // => tests
}
// </ComposeWithCaching>
}
}Grouping is useful for summaries, reports, and menus. For more information about joins, nested groupings, and provider-specific behavior, see Language Integrated Query (LINQ).
Run a query
Many LINQ operators use deferred execution. Deferred execution means operators that return a sequence, such as System.Linq.Enumerable.Where, System.Linq.Enumerable.Select, and System.Linq.Enumerable.OrderBy, don't run when you define them. They build the recipe for producing results. A foreach loop is one way to run that recipe:
sample · csharpdocs/csharp/fundamentals/statements/snippets/linq-statements/Program.csDeferredExecution
namespace LinqStatements;
public static class Program
{
public static void Main()
{
QuerySyntaxExample();
MethodSyntaxExample();
QuerySyntaxClearerExample();
MethodSyntaxClearerExample();
LambdaExpressionsExample();
QuerySyntaxLambdaExample();
CommonOperatorsExample();
GroupByExample();
DeferredExecutionExample();
ImmediateExecutionExample();
ComposeQuerySyntaxExample();
ComposeMethodSyntaxExample();
ComposeWithCachingExample();
}
private static void QuerySyntaxExample()
{
// <QuerySyntax>
string[] names = ["Ana", "Ben", "Cleo", "Dara"];
IEnumerable<string> query =
from name in names
where name.Length >= 4
orderby name
select name;
foreach (string name in query)
{
Console.WriteLine(name);
}
// This example produces the following output:
//
// Cleo
// Dara
//
// </QuerySyntax>
}
private static void MethodSyntaxExample()
{
// <MethodSyntax>
string[] names = ["Ana", "Ben", "Cleo", "Dara"];
IEnumerable<string> query = names
.Where(name => name.Length >= 4)
.OrderBy(name => name)
.Select(name => name);
foreach (string name in query)
{
Console.WriteLine(name);
}
// This example produces the following output:
//
// Cleo
// Dara
//
// </MethodSyntax>
}
private static void QuerySyntaxClearerExample()
{
// <QuerySyntaxClearer>
(string Area, int Priority)[] workItems =
[
("docs", 2),
("tests", 1),
("deploy", 4),
("api", 1)
];
IEnumerable<string> nextItems =
from item in workItems
let label = $"{item.Area}: P{item.Priority}"
where item.Priority <= 2
orderby item.Priority, item.Area
select label;
foreach (string item in nextItems)
{
Console.WriteLine(item);
}
// This example produces the following output:
//
// api: P1
// tests: P1
// docs: P2
//
// </QuerySyntaxClearer>
}
private static void MethodSyntaxClearerExample()
{
// <MethodSyntaxClearer>
List<string> workItems = ["design", "docs", "deploy", "review"];
int count = workItems.Count(item => item.StartsWith('d'));
Console.WriteLine($"Starts with d: {count}"); // => Starts with d: 3
// </MethodSyntaxClearer>
}
private static void LambdaExpressionsExample()
{
// <LambdaExpressions>
string[] names = ["Ana", "Ben", "Cleo"];
IEnumerable<string> shortNames = names
.Where(name => name.Length == 3)
.Select(name => name.ToUpperInvariant());
foreach (string name in shortNames)
{
Console.WriteLine(name);
}
// This example produces the following output:
//
// ANA
// BEN
//
// </LambdaExpressions>
}
private static void QuerySyntaxLambdaExample()
{
// <QuerySyntaxLambda>
string[] workItems = ["docs", "test", "deploy"];
IEnumerable<string> querySyntax =
from item in workItems
where item.Length == 4
select item;
IEnumerable<string> methodSyntax =
workItems.Where(item => item.Length == 4);
foreach (string item in querySyntax)
{
Console.WriteLine($"Result: {item}");
}
foreach (string item in methodSyntax)
{
Console.WriteLine($"Result: {item}");
}
// This example produces the following output:
//
// Result: docs
// Result: test
// Result: docs
// Result: test
//
// </QuerySyntaxLambda>
}
private static void CommonOperatorsExample()
{
// <CommonOperators>
Dictionary<string, int> priorities = new()
{
["Docs"] = 2,
["Code"] = 1,
["Test"] = 3,
["Deploy"] = 4
};
IEnumerable<string> plannedWork = priorities
.Where(workItem => workItem.Value <= 3)
.OrderBy(workItem => workItem.Value)
.Select(workItem => $"{workItem.Key}: {workItem.Value}");
foreach (string item in plannedWork)
{
Console.WriteLine(item);
}
// This example produces the following output:
//
// Code: 1
// Docs: 2
// Test: 3
//
// </CommonOperators>
}
private static void GroupByExample()
{
// <GroupBy>
string[] labels = ["api", "auth", "docs", "deploy"];
IEnumerable<IGrouping<char, string>> groups = labels.GroupBy(label => label[0]);
foreach (IGrouping<char, string> group in groups)
{
Console.WriteLine($"{group.Key}: {string.Join(", ", group)}");
}
// This example produces the following output:
//
// a: api, auth
// d: docs, deploy
//
// </GroupBy>
}
private static void DeferredExecutionExample()
{
// <DeferredExecution>
List<string> workItems = ["design", "docs"];
IEnumerable<string> query = workItems.Where(item => item.StartsWith('d'));
workItems.Add("deploy");
// The query runs here, when foreach asks for the results.
foreach (string item in query)
{
Console.WriteLine(item);
}
// This example produces the following output:
//
// design
// docs
// deploy
//
// </DeferredExecution>
}
private static void ImmediateExecutionExample()
{
// <ImmediateExecution>
List<string> workItems = ["design", "docs"];
IEnumerable<string> query = workItems.Where(item => item.StartsWith('d'));
// Count() reads the matching elements right when this line runs.
int count = query.Count();
Console.WriteLine($"Count before add: {count}");
workItems.Add("deploy");
Console.WriteLine($"Stored count: {count}");
Console.WriteLine($"Current count: {query.Count()}");
// This example produces the following output:
//
// Count before add: 2
// Stored count: 2
// Current count: 3
//
// </ImmediateExecution>
}
private static void ComposeQuerySyntaxExample()
{
// <ComposeQuerySyntax>
(string Title, int Priority, bool IsOpen)[] items =
[
("docs", 2, true),
("tests", 1, true),
("deploy", 3, false),
("api", 1, true)
];
IEnumerable<(string Title, int Priority, bool IsOpen)> openItems =
from item in items
where item.IsOpen
select item;
IEnumerable<string> topOpenItems =
from item in openItems
where item.Priority == 1
orderby item.Title
select item.Title;
foreach (string title in topOpenItems)
{
Console.WriteLine(title);
}
// This example produces the following output:
//
// api
// tests
//
// </ComposeQuerySyntax>
}
private static void ComposeMethodSyntaxExample()
{
// <ComposeMethodSyntax>
(string Title, string Area, bool IsOpen)[] items =
[
("write docs", "docs", true),
("fix tests", "tests", true),
("deploy site", "deploy", false)
];
bool onlyDocs = true;
IEnumerable<(string Title, string Area, bool IsOpen)> query =
items.Where(item => item.IsOpen);
if (onlyDocs)
{
query = query.Where(item => item.Area == "docs");
}
foreach (string title in query.Select(item => item.Title))
{
Console.WriteLine(title); // => write docs
}
// </ComposeMethodSyntax>
}
private static void ComposeWithCachingExample()
{
// <ComposeWithCaching>
List<(string Title, int Priority, bool IsOpen)> items =
[
("docs", 2, true),
("tests", 1, true),
("deploy", 3, false)
];
List<(string Title, int Priority, bool IsOpen)> openItems = items
.Where(item => item.IsOpen)
.ToList();
items.Add(("api", 1, true));
IEnumerable<string> cachedTopOpenItems = openItems
.Where(item => item.Priority == 1)
.OrderBy(item => item.Title)
.Select(item => item.Title);
foreach (string title in cachedTopOpenItems)
{
Console.WriteLine(title); // => tests
}
// </ComposeWithCaching>
}
}Other operations run a query immediately. Operators that return a single value, such as System.Linq.Enumerable.Count, System.Linq.Enumerable.Sum, System.Linq.Enumerable.First, and System.Linq.Enumerable.Any, must read the elements when you call them so they can produce that value.
sample · csharpdocs/csharp/fundamentals/statements/snippets/linq-statements/Program.csImmediateExecution
namespace LinqStatements;
public static class Program
{
public static void Main()
{
QuerySyntaxExample();
MethodSyntaxExample();
QuerySyntaxClearerExample();
MethodSyntaxClearerExample();
LambdaExpressionsExample();
QuerySyntaxLambdaExample();
CommonOperatorsExample();
GroupByExample();
DeferredExecutionExample();
ImmediateExecutionExample();
ComposeQuerySyntaxExample();
ComposeMethodSyntaxExample();
ComposeWithCachingExample();
}
private static void QuerySyntaxExample()
{
// <QuerySyntax>
string[] names = ["Ana", "Ben", "Cleo", "Dara"];
IEnumerable<string> query =
from name in names
where name.Length >= 4
orderby name
select name;
foreach (string name in query)
{
Console.WriteLine(name);
}
// This example produces the following output:
//
// Cleo
// Dara
//
// </QuerySyntax>
}
private static void MethodSyntaxExample()
{
// <MethodSyntax>
string[] names = ["Ana", "Ben", "Cleo", "Dara"];
IEnumerable<string> query = names
.Where(name => name.Length >= 4)
.OrderBy(name => name)
.Select(name => name);
foreach (string name in query)
{
Console.WriteLine(name);
}
// This example produces the following output:
//
// Cleo
// Dara
//
// </MethodSyntax>
}
private static void QuerySyntaxClearerExample()
{
// <QuerySyntaxClearer>
(string Area, int Priority)[] workItems =
[
("docs", 2),
("tests", 1),
("deploy", 4),
("api", 1)
];
IEnumerable<string> nextItems =
from item in workItems
let label = $"{item.Area}: P{item.Priority}"
where item.Priority <= 2
orderby item.Priority, item.Area
select label;
foreach (string item in nextItems)
{
Console.WriteLine(item);
}
// This example produces the following output:
//
// api: P1
// tests: P1
// docs: P2
//
// </QuerySyntaxClearer>
}
private static void MethodSyntaxClearerExample()
{
// <MethodSyntaxClearer>
List<string> workItems = ["design", "docs", "deploy", "review"];
int count = workItems.Count(item => item.StartsWith('d'));
Console.WriteLine($"Starts with d: {count}"); // => Starts with d: 3
// </MethodSyntaxClearer>
}
private static void LambdaExpressionsExample()
{
// <LambdaExpressions>
string[] names = ["Ana", "Ben", "Cleo"];
IEnumerable<string> shortNames = names
.Where(name => name.Length == 3)
.Select(name => name.ToUpperInvariant());
foreach (string name in shortNames)
{
Console.WriteLine(name);
}
// This example produces the following output:
//
// ANA
// BEN
//
// </LambdaExpressions>
}
private static void QuerySyntaxLambdaExample()
{
// <QuerySyntaxLambda>
string[] workItems = ["docs", "test", "deploy"];
IEnumerable<string> querySyntax =
from item in workItems
where item.Length == 4
select item;
IEnumerable<string> methodSyntax =
workItems.Where(item => item.Length == 4);
foreach (string item in querySyntax)
{
Console.WriteLine($"Result: {item}");
}
foreach (string item in methodSyntax)
{
Console.WriteLine($"Result: {item}");
}
// This example produces the following output:
//
// Result: docs
// Result: test
// Result: docs
// Result: test
//
// </QuerySyntaxLambda>
}
private static void CommonOperatorsExample()
{
// <CommonOperators>
Dictionary<string, int> priorities = new()
{
["Docs"] = 2,
["Code"] = 1,
["Test"] = 3,
["Deploy"] = 4
};
IEnumerable<string> plannedWork = priorities
.Where(workItem => workItem.Value <= 3)
.OrderBy(workItem => workItem.Value)
.Select(workItem => $"{workItem.Key}: {workItem.Value}");
foreach (string item in plannedWork)
{
Console.WriteLine(item);
}
// This example produces the following output:
//
// Code: 1
// Docs: 2
// Test: 3
//
// </CommonOperators>
}
private static void GroupByExample()
{
// <GroupBy>
string[] labels = ["api", "auth", "docs", "deploy"];
IEnumerable<IGrouping<char, string>> groups = labels.GroupBy(label => label[0]);
foreach (IGrouping<char, string> group in groups)
{
Console.WriteLine($"{group.Key}: {string.Join(", ", group)}");
}
// This example produces the following output:
//
// a: api, auth
// d: docs, deploy
//
// </GroupBy>
}
private static void DeferredExecutionExample()
{
// <DeferredExecution>
List<string> workItems = ["design", "docs"];
IEnumerable<string> query = workItems.Where(item => item.StartsWith('d'));
workItems.Add("deploy");
// The query runs here, when foreach asks for the results.
foreach (string item in query)
{
Console.WriteLine(item);
}
// This example produces the following output:
//
// design
// docs
// deploy
//
// </DeferredExecution>
}
private static void ImmediateExecutionExample()
{
// <ImmediateExecution>
List<string> workItems = ["design", "docs"];
IEnumerable<string> query = workItems.Where(item => item.StartsWith('d'));
// Count() reads the matching elements right when this line runs.
int count = query.Count();
Console.WriteLine($"Count before add: {count}");
workItems.Add("deploy");
Console.WriteLine($"Stored count: {count}");
Console.WriteLine($"Current count: {query.Count()}");
// This example produces the following output:
//
// Count before add: 2
// Stored count: 2
// Current count: 3
//
// </ImmediateExecution>
}
private static void ComposeQuerySyntaxExample()
{
// <ComposeQuerySyntax>
(string Title, int Priority, bool IsOpen)[] items =
[
("docs", 2, true),
("tests", 1, true),
("deploy", 3, false),
("api", 1, true)
];
IEnumerable<(string Title, int Priority, bool IsOpen)> openItems =
from item in items
where item.IsOpen
select item;
IEnumerable<string> topOpenItems =
from item in openItems
where item.Priority == 1
orderby item.Title
select item.Title;
foreach (string title in topOpenItems)
{
Console.WriteLine(title);
}
// This example produces the following output:
//
// api
// tests
//
// </ComposeQuerySyntax>
}
private static void ComposeMethodSyntaxExample()
{
// <ComposeMethodSyntax>
(string Title, string Area, bool IsOpen)[] items =
[
("write docs", "docs", true),
("fix tests", "tests", true),
("deploy site", "deploy", false)
];
bool onlyDocs = true;
IEnumerable<(string Title, string Area, bool IsOpen)> query =
items.Where(item => item.IsOpen);
if (onlyDocs)
{
query = query.Where(item => item.Area == "docs");
}
foreach (string title in query.Select(item => item.Title))
{
Console.WriteLine(title); // => write docs
}
// </ComposeMethodSyntax>
}
private static void ComposeWithCachingExample()
{
// <ComposeWithCaching>
List<(string Title, int Priority, bool IsOpen)> items =
[
("docs", 2, true),
("tests", 1, true),
("deploy", 3, false)
];
List<(string Title, int Priority, bool IsOpen)> openItems = items
.Where(item => item.IsOpen)
.ToList();
items.Add(("api", 1, true));
IEnumerable<string> cachedTopOpenItems = openItems
.Where(item => item.Priority == 1)
.OrderBy(item => item.Title)
.Select(item => item.Title);
foreach (string title in cachedTopOpenItems)
{
Console.WriteLine(title); // => tests
}
// </ComposeWithCaching>
}
}There's no single trigger that runs a query. Eager evaluation, also called immediate evaluation, runs the query right away and stores or returns the result. Scalar and aggregate operators such as System.Linq.Enumerable.Count, System.Linq.Enumerable.Sum, System.Linq.Enumerable.First, and System.Linq.Enumerable.Any use eager evaluation. So do System.Linq.Enumerable.ToList and System.Linq.Enumerable.ToArray when you need a snapshot of the current results. For more information about deferred execution, see Introduction to LINQ Queries in the LINQ documentation.
Compose queries
Real queries often grow from smaller decisions: start with a shared filter, add a sort for one screen, or apply an optional condition from user input. By composing queries, you can keep each step readable and reuse common parts instead of repeating one large query.
Imagine an app that shows open work items in several places. One view needs all open items, and another view needs only the highest-priority open items. To compose a query, start with a base query stored in a variable, then build a more specific query from it. Because execution is deferred, each step describes more of the result. No work happens until you enumerate the final query.
The following example stores the open work items in one query, then reuses that query to find the highest-priority open items:
sample · csharpdocs/csharp/fundamentals/statements/snippets/linq-statements/Program.csComposeQuerySyntax
namespace LinqStatements;
public static class Program
{
public static void Main()
{
QuerySyntaxExample();
MethodSyntaxExample();
QuerySyntaxClearerExample();
MethodSyntaxClearerExample();
LambdaExpressionsExample();
QuerySyntaxLambdaExample();
CommonOperatorsExample();
GroupByExample();
DeferredExecutionExample();
ImmediateExecutionExample();
ComposeQuerySyntaxExample();
ComposeMethodSyntaxExample();
ComposeWithCachingExample();
}
private static void QuerySyntaxExample()
{
// <QuerySyntax>
string[] names = ["Ana", "Ben", "Cleo", "Dara"];
IEnumerable<string> query =
from name in names
where name.Length >= 4
orderby name
select name;
foreach (string name in query)
{
Console.WriteLine(name);
}
// This example produces the following output:
//
// Cleo
// Dara
//
// </QuerySyntax>
}
private static void MethodSyntaxExample()
{
// <MethodSyntax>
string[] names = ["Ana", "Ben", "Cleo", "Dara"];
IEnumerable<string> query = names
.Where(name => name.Length >= 4)
.OrderBy(name => name)
.Select(name => name);
foreach (string name in query)
{
Console.WriteLine(name);
}
// This example produces the following output:
//
// Cleo
// Dara
//
// </MethodSyntax>
}
private static void QuerySyntaxClearerExample()
{
// <QuerySyntaxClearer>
(string Area, int Priority)[] workItems =
[
("docs", 2),
("tests", 1),
("deploy", 4),
("api", 1)
];
IEnumerable<string> nextItems =
from item in workItems
let label = $"{item.Area}: P{item.Priority}"
where item.Priority <= 2
orderby item.Priority, item.Area
select label;
foreach (string item in nextItems)
{
Console.WriteLine(item);
}
// This example produces the following output:
//
// api: P1
// tests: P1
// docs: P2
//
// </QuerySyntaxClearer>
}
private static void MethodSyntaxClearerExample()
{
// <MethodSyntaxClearer>
List<string> workItems = ["design", "docs", "deploy", "review"];
int count = workItems.Count(item => item.StartsWith('d'));
Console.WriteLine($"Starts with d: {count}"); // => Starts with d: 3
// </MethodSyntaxClearer>
}
private static void LambdaExpressionsExample()
{
// <LambdaExpressions>
string[] names = ["Ana", "Ben", "Cleo"];
IEnumerable<string> shortNames = names
.Where(name => name.Length == 3)
.Select(name => name.ToUpperInvariant());
foreach (string name in shortNames)
{
Console.WriteLine(name);
}
// This example produces the following output:
//
// ANA
// BEN
//
// </LambdaExpressions>
}
private static void QuerySyntaxLambdaExample()
{
// <QuerySyntaxLambda>
string[] workItems = ["docs", "test", "deploy"];
IEnumerable<string> querySyntax =
from item in workItems
where item.Length == 4
select item;
IEnumerable<string> methodSyntax =
workItems.Where(item => item.Length == 4);
foreach (string item in querySyntax)
{
Console.WriteLine($"Result: {item}");
}
foreach (string item in methodSyntax)
{
Console.WriteLine($"Result: {item}");
}
// This example produces the following output:
//
// Result: docs
// Result: test
// Result: docs
// Result: test
//
// </QuerySyntaxLambda>
}
private static void CommonOperatorsExample()
{
// <CommonOperators>
Dictionary<string, int> priorities = new()
{
["Docs"] = 2,
["Code"] = 1,
["Test"] = 3,
["Deploy"] = 4
};
IEnumerable<string> plannedWork = priorities
.Where(workItem => workItem.Value <= 3)
.OrderBy(workItem => workItem.Value)
.Select(workItem => $"{workItem.Key}: {workItem.Value}");
foreach (string item in plannedWork)
{
Console.WriteLine(item);
}
// This example produces the following output:
//
// Code: 1
// Docs: 2
// Test: 3
//
// </CommonOperators>
}
private static void GroupByExample()
{
// <GroupBy>
string[] labels = ["api", "auth", "docs", "deploy"];
IEnumerable<IGrouping<char, string>> groups = labels.GroupBy(label => label[0]);
foreach (IGrouping<char, string> group in groups)
{
Console.WriteLine($"{group.Key}: {string.Join(", ", group)}");
}
// This example produces the following output:
//
// a: api, auth
// d: docs, deploy
//
// </GroupBy>
}
private static void DeferredExecutionExample()
{
// <DeferredExecution>
List<string> workItems = ["design", "docs"];
IEnumerable<string> query = workItems.Where(item => item.StartsWith('d'));
workItems.Add("deploy");
// The query runs here, when foreach asks for the results.
foreach (string item in query)
{
Console.WriteLine(item);
}
// This example produces the following output:
//
// design
// docs
// deploy
//
// </DeferredExecution>
}
private static void ImmediateExecutionExample()
{
// <ImmediateExecution>
List<string> workItems = ["design", "docs"];
IEnumerable<string> query = workItems.Where(item => item.StartsWith('d'));
// Count() reads the matching elements right when this line runs.
int count = query.Count();
Console.WriteLine($"Count before add: {count}");
workItems.Add("deploy");
Console.WriteLine($"Stored count: {count}");
Console.WriteLine($"Current count: {query.Count()}");
// This example produces the following output:
//
// Count before add: 2
// Stored count: 2
// Current count: 3
//
// </ImmediateExecution>
}
private static void ComposeQuerySyntaxExample()
{
// <ComposeQuerySyntax>
(string Title, int Priority, bool IsOpen)[] items =
[
("docs", 2, true),
("tests", 1, true),
("deploy", 3, false),
("api", 1, true)
];
IEnumerable<(string Title, int Priority, bool IsOpen)> openItems =
from item in items
where item.IsOpen
select item;
IEnumerable<string> topOpenItems =
from item in openItems
where item.Priority == 1
orderby item.Title
select item.Title;
foreach (string title in topOpenItems)
{
Console.WriteLine(title);
}
// This example produces the following output:
//
// api
// tests
//
// </ComposeQuerySyntax>
}
private static void ComposeMethodSyntaxExample()
{
// <ComposeMethodSyntax>
(string Title, string Area, bool IsOpen)[] items =
[
("write docs", "docs", true),
("fix tests", "tests", true),
("deploy site", "deploy", false)
];
bool onlyDocs = true;
IEnumerable<(string Title, string Area, bool IsOpen)> query =
items.Where(item => item.IsOpen);
if (onlyDocs)
{
query = query.Where(item => item.Area == "docs");
}
foreach (string title in query.Select(item => item.Title))
{
Console.WriteLine(title); // => write docs
}
// </ComposeMethodSyntax>
}
private static void ComposeWithCachingExample()
{
// <ComposeWithCaching>
List<(string Title, int Priority, bool IsOpen)> items =
[
("docs", 2, true),
("tests", 1, true),
("deploy", 3, false)
];
List<(string Title, int Priority, bool IsOpen)> openItems = items
.Where(item => item.IsOpen)
.ToList();
items.Add(("api", 1, true));
IEnumerable<string> cachedTopOpenItems = openItems
.Where(item => item.Priority == 1)
.OrderBy(item => item.Title)
.Select(item => item.Title);
foreach (string title in cachedTopOpenItems)
{
Console.WriteLine(title); // => tests
}
// </ComposeWithCaching>
}
}You can also compose queries with method syntax. The next example starts with all open items, then conditionally adds another filter before it selects the titles:
sample · csharpdocs/csharp/fundamentals/statements/snippets/linq-statements/Program.csComposeMethodSyntax
namespace LinqStatements;
public static class Program
{
public static void Main()
{
QuerySyntaxExample();
MethodSyntaxExample();
QuerySyntaxClearerExample();
MethodSyntaxClearerExample();
LambdaExpressionsExample();
QuerySyntaxLambdaExample();
CommonOperatorsExample();
GroupByExample();
DeferredExecutionExample();
ImmediateExecutionExample();
ComposeQuerySyntaxExample();
ComposeMethodSyntaxExample();
ComposeWithCachingExample();
}
private static void QuerySyntaxExample()
{
// <QuerySyntax>
string[] names = ["Ana", "Ben", "Cleo", "Dara"];
IEnumerable<string> query =
from name in names
where name.Length >= 4
orderby name
select name;
foreach (string name in query)
{
Console.WriteLine(name);
}
// This example produces the following output:
//
// Cleo
// Dara
//
// </QuerySyntax>
}
private static void MethodSyntaxExample()
{
// <MethodSyntax>
string[] names = ["Ana", "Ben", "Cleo", "Dara"];
IEnumerable<string> query = names
.Where(name => name.Length >= 4)
.OrderBy(name => name)
.Select(name => name);
foreach (string name in query)
{
Console.WriteLine(name);
}
// This example produces the following output:
//
// Cleo
// Dara
//
// </MethodSyntax>
}
private static void QuerySyntaxClearerExample()
{
// <QuerySyntaxClearer>
(string Area, int Priority)[] workItems =
[
("docs", 2),
("tests", 1),
("deploy", 4),
("api", 1)
];
IEnumerable<string> nextItems =
from item in workItems
let label = $"{item.Area}: P{item.Priority}"
where item.Priority <= 2
orderby item.Priority, item.Area
select label;
foreach (string item in nextItems)
{
Console.WriteLine(item);
}
// This example produces the following output:
//
// api: P1
// tests: P1
// docs: P2
//
// </QuerySyntaxClearer>
}
private static void MethodSyntaxClearerExample()
{
// <MethodSyntaxClearer>
List<string> workItems = ["design", "docs", "deploy", "review"];
int count = workItems.Count(item => item.StartsWith('d'));
Console.WriteLine($"Starts with d: {count}"); // => Starts with d: 3
// </MethodSyntaxClearer>
}
private static void LambdaExpressionsExample()
{
// <LambdaExpressions>
string[] names = ["Ana", "Ben", "Cleo"];
IEnumerable<string> shortNames = names
.Where(name => name.Length == 3)
.Select(name => name.ToUpperInvariant());
foreach (string name in shortNames)
{
Console.WriteLine(name);
}
// This example produces the following output:
//
// ANA
// BEN
//
// </LambdaExpressions>
}
private static void QuerySyntaxLambdaExample()
{
// <QuerySyntaxLambda>
string[] workItems = ["docs", "test", "deploy"];
IEnumerable<string> querySyntax =
from item in workItems
where item.Length == 4
select item;
IEnumerable<string> methodSyntax =
workItems.Where(item => item.Length == 4);
foreach (string item in querySyntax)
{
Console.WriteLine($"Result: {item}");
}
foreach (string item in methodSyntax)
{
Console.WriteLine($"Result: {item}");
}
// This example produces the following output:
//
// Result: docs
// Result: test
// Result: docs
// Result: test
//
// </QuerySyntaxLambda>
}
private static void CommonOperatorsExample()
{
// <CommonOperators>
Dictionary<string, int> priorities = new()
{
["Docs"] = 2,
["Code"] = 1,
["Test"] = 3,
["Deploy"] = 4
};
IEnumerable<string> plannedWork = priorities
.Where(workItem => workItem.Value <= 3)
.OrderBy(workItem => workItem.Value)
.Select(workItem => $"{workItem.Key}: {workItem.Value}");
foreach (string item in plannedWork)
{
Console.WriteLine(item);
}
// This example produces the following output:
//
// Code: 1
// Docs: 2
// Test: 3
//
// </CommonOperators>
}
private static void GroupByExample()
{
// <GroupBy>
string[] labels = ["api", "auth", "docs", "deploy"];
IEnumerable<IGrouping<char, string>> groups = labels.GroupBy(label => label[0]);
foreach (IGrouping<char, string> group in groups)
{
Console.WriteLine($"{group.Key}: {string.Join(", ", group)}");
}
// This example produces the following output:
//
// a: api, auth
// d: docs, deploy
//
// </GroupBy>
}
private static void DeferredExecutionExample()
{
// <DeferredExecution>
List<string> workItems = ["design", "docs"];
IEnumerable<string> query = workItems.Where(item => item.StartsWith('d'));
workItems.Add("deploy");
// The query runs here, when foreach asks for the results.
foreach (string item in query)
{
Console.WriteLine(item);
}
// This example produces the following output:
//
// design
// docs
// deploy
//
// </DeferredExecution>
}
private static void ImmediateExecutionExample()
{
// <ImmediateExecution>
List<string> workItems = ["design", "docs"];
IEnumerable<string> query = workItems.Where(item => item.StartsWith('d'));
// Count() reads the matching elements right when this line runs.
int count = query.Count();
Console.WriteLine($"Count before add: {count}");
workItems.Add("deploy");
Console.WriteLine($"Stored count: {count}");
Console.WriteLine($"Current count: {query.Count()}");
// This example produces the following output:
//
// Count before add: 2
// Stored count: 2
// Current count: 3
//
// </ImmediateExecution>
}
private static void ComposeQuerySyntaxExample()
{
// <ComposeQuerySyntax>
(string Title, int Priority, bool IsOpen)[] items =
[
("docs", 2, true),
("tests", 1, true),
("deploy", 3, false),
("api", 1, true)
];
IEnumerable<(string Title, int Priority, bool IsOpen)> openItems =
from item in items
where item.IsOpen
select item;
IEnumerable<string> topOpenItems =
from item in openItems
where item.Priority == 1
orderby item.Title
select item.Title;
foreach (string title in topOpenItems)
{
Console.WriteLine(title);
}
// This example produces the following output:
//
// api
// tests
//
// </ComposeQuerySyntax>
}
private static void ComposeMethodSyntaxExample()
{
// <ComposeMethodSyntax>
(string Title, string Area, bool IsOpen)[] items =
[
("write docs", "docs", true),
("fix tests", "tests", true),
("deploy site", "deploy", false)
];
bool onlyDocs = true;
IEnumerable<(string Title, string Area, bool IsOpen)> query =
items.Where(item => item.IsOpen);
if (onlyDocs)
{
query = query.Where(item => item.Area == "docs");
}
foreach (string title in query.Select(item => item.Title))
{
Console.WriteLine(title); // => write docs
}
// </ComposeMethodSyntax>
}
private static void ComposeWithCachingExample()
{
// <ComposeWithCaching>
List<(string Title, int Priority, bool IsOpen)> items =
[
("docs", 2, true),
("tests", 1, true),
("deploy", 3, false)
];
List<(string Title, int Priority, bool IsOpen)> openItems = items
.Where(item => item.IsOpen)
.ToList();
items.Add(("api", 1, true));
IEnumerable<string> cachedTopOpenItems = openItems
.Where(item => item.Priority == 1)
.OrderBy(item => item.Title)
.Select(item => item.Title);
foreach (string title in cachedTopOpenItems)
{
Console.WriteLine(title); // => tests
}
// </ComposeWithCaching>
}
}Composition can use either or both eager evaluation and deferred execution. Materialize a shared intermediate result with System.Linq.Enumerable.ToList or System.Linq.Enumerable.ToArray when you want that part to run once and stay fixed. Then build another deferred query from the cached results for the final output:
sample · csharpdocs/csharp/fundamentals/statements/snippets/linq-statements/Program.csComposeWithCaching
namespace LinqStatements;
public static class Program
{
public static void Main()
{
QuerySyntaxExample();
MethodSyntaxExample();
QuerySyntaxClearerExample();
MethodSyntaxClearerExample();
LambdaExpressionsExample();
QuerySyntaxLambdaExample();
CommonOperatorsExample();
GroupByExample();
DeferredExecutionExample();
ImmediateExecutionExample();
ComposeQuerySyntaxExample();
ComposeMethodSyntaxExample();
ComposeWithCachingExample();
}
private static void QuerySyntaxExample()
{
// <QuerySyntax>
string[] names = ["Ana", "Ben", "Cleo", "Dara"];
IEnumerable<string> query =
from name in names
where name.Length >= 4
orderby name
select name;
foreach (string name in query)
{
Console.WriteLine(name);
}
// This example produces the following output:
//
// Cleo
// Dara
//
// </QuerySyntax>
}
private static void MethodSyntaxExample()
{
// <MethodSyntax>
string[] names = ["Ana", "Ben", "Cleo", "Dara"];
IEnumerable<string> query = names
.Where(name => name.Length >= 4)
.OrderBy(name => name)
.Select(name => name);
foreach (string name in query)
{
Console.WriteLine(name);
}
// This example produces the following output:
//
// Cleo
// Dara
//
// </MethodSyntax>
}
private static void QuerySyntaxClearerExample()
{
// <QuerySyntaxClearer>
(string Area, int Priority)[] workItems =
[
("docs", 2),
("tests", 1),
("deploy", 4),
("api", 1)
];
IEnumerable<string> nextItems =
from item in workItems
let label = $"{item.Area}: P{item.Priority}"
where item.Priority <= 2
orderby item.Priority, item.Area
select label;
foreach (string item in nextItems)
{
Console.WriteLine(item);
}
// This example produces the following output:
//
// api: P1
// tests: P1
// docs: P2
//
// </QuerySyntaxClearer>
}
private static void MethodSyntaxClearerExample()
{
// <MethodSyntaxClearer>
List<string> workItems = ["design", "docs", "deploy", "review"];
int count = workItems.Count(item => item.StartsWith('d'));
Console.WriteLine($"Starts with d: {count}"); // => Starts with d: 3
// </MethodSyntaxClearer>
}
private static void LambdaExpressionsExample()
{
// <LambdaExpressions>
string[] names = ["Ana", "Ben", "Cleo"];
IEnumerable<string> shortNames = names
.Where(name => name.Length == 3)
.Select(name => name.ToUpperInvariant());
foreach (string name in shortNames)
{
Console.WriteLine(name);
}
// This example produces the following output:
//
// ANA
// BEN
//
// </LambdaExpressions>
}
private static void QuerySyntaxLambdaExample()
{
// <QuerySyntaxLambda>
string[] workItems = ["docs", "test", "deploy"];
IEnumerable<string> querySyntax =
from item in workItems
where item.Length == 4
select item;
IEnumerable<string> methodSyntax =
workItems.Where(item => item.Length == 4);
foreach (string item in querySyntax)
{
Console.WriteLine($"Result: {item}");
}
foreach (string item in methodSyntax)
{
Console.WriteLine($"Result: {item}");
}
// This example produces the following output:
//
// Result: docs
// Result: test
// Result: docs
// Result: test
//
// </QuerySyntaxLambda>
}
private static void CommonOperatorsExample()
{
// <CommonOperators>
Dictionary<string, int> priorities = new()
{
["Docs"] = 2,
["Code"] = 1,
["Test"] = 3,
["Deploy"] = 4
};
IEnumerable<string> plannedWork = priorities
.Where(workItem => workItem.Value <= 3)
.OrderBy(workItem => workItem.Value)
.Select(workItem => $"{workItem.Key}: {workItem.Value}");
foreach (string item in plannedWork)
{
Console.WriteLine(item);
}
// This example produces the following output:
//
// Code: 1
// Docs: 2
// Test: 3
//
// </CommonOperators>
}
private static void GroupByExample()
{
// <GroupBy>
string[] labels = ["api", "auth", "docs", "deploy"];
IEnumerable<IGrouping<char, string>> groups = labels.GroupBy(label => label[0]);
foreach (IGrouping<char, string> group in groups)
{
Console.WriteLine($"{group.Key}: {string.Join(", ", group)}");
}
// This example produces the following output:
//
// a: api, auth
// d: docs, deploy
//
// </GroupBy>
}
private static void DeferredExecutionExample()
{
// <DeferredExecution>
List<string> workItems = ["design", "docs"];
IEnumerable<string> query = workItems.Where(item => item.StartsWith('d'));
workItems.Add("deploy");
// The query runs here, when foreach asks for the results.
foreach (string item in query)
{
Console.WriteLine(item);
}
// This example produces the following output:
//
// design
// docs
// deploy
//
// </DeferredExecution>
}
private static void ImmediateExecutionExample()
{
// <ImmediateExecution>
List<string> workItems = ["design", "docs"];
IEnumerable<string> query = workItems.Where(item => item.StartsWith('d'));
// Count() reads the matching elements right when this line runs.
int count = query.Count();
Console.WriteLine($"Count before add: {count}");
workItems.Add("deploy");
Console.WriteLine($"Stored count: {count}");
Console.WriteLine($"Current count: {query.Count()}");
// This example produces the following output:
//
// Count before add: 2
// Stored count: 2
// Current count: 3
//
// </ImmediateExecution>
}
private static void ComposeQuerySyntaxExample()
{
// <ComposeQuerySyntax>
(string Title, int Priority, bool IsOpen)[] items =
[
("docs", 2, true),
("tests", 1, true),
("deploy", 3, false),
("api", 1, true)
];
IEnumerable<(string Title, int Priority, bool IsOpen)> openItems =
from item in items
where item.IsOpen
select item;
IEnumerable<string> topOpenItems =
from item in openItems
where item.Priority == 1
orderby item.Title
select item.Title;
foreach (string title in topOpenItems)
{
Console.WriteLine(title);
}
// This example produces the following output:
//
// api
// tests
//
// </ComposeQuerySyntax>
}
private static void ComposeMethodSyntaxExample()
{
// <ComposeMethodSyntax>
(string Title, string Area, bool IsOpen)[] items =
[
("write docs", "docs", true),
("fix tests", "tests", true),
("deploy site", "deploy", false)
];
bool onlyDocs = true;
IEnumerable<(string Title, string Area, bool IsOpen)> query =
items.Where(item => item.IsOpen);
if (onlyDocs)
{
query = query.Where(item => item.Area == "docs");
}
foreach (string title in query.Select(item => item.Title))
{
Console.WriteLine(title); // => write docs
}
// </ComposeMethodSyntax>
}
private static void ComposeWithCachingExample()
{
// <ComposeWithCaching>
List<(string Title, int Priority, bool IsOpen)> items =
[
("docs", 2, true),
("tests", 1, true),
("deploy", 3, false)
];
List<(string Title, int Priority, bool IsOpen)> openItems = items
.Where(item => item.IsOpen)
.ToList();
items.Add(("api", 1, true));
IEnumerable<string> cachedTopOpenItems = openItems
.Where(item => item.Priority == 1)
.OrderBy(item => item.Title)
.Select(item => item.Title);
foreach (string title in cachedTopOpenItems)
{
Console.WriteLine(title); // => tests
}
// </ComposeWithCaching>
}
}Explore LINQ in depth
This article uses in-memory collections to teach LINQ syntax and core operators. For more information about LINQ operators and advanced scenarios, see Language Integrated Query (LINQ). That article covers joins, XML, database providers, dynamic queries, and custom operators.