Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions docs/csharp/advanced-topics/expression-trees/index.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
---
title: "Expression Trees"
description: Learn about expression trees. See how to compile and run code represented by these data structures, where each node is an expression.
ms.date: 03/07/2023
ms.date: 05/29/2024
ms.custom: updateeachrelease
---
# Expression Trees

*Expression trees* represent code in a tree-like data structure, where each node is an expression, for example, a method call or a binary operation such as `x < y`.

If you have used LINQ, you have experience with a rich library where the `Func` types are part of the API set. (If you aren't familiar with LINQ, you probably want to read [the LINQ tutorial](/dotnet/csharp/linq/) and the article about [lambda expressions](../../language-reference/operators/lambda-expressions.md) before this one.) Expression Trees provide richer interaction with the arguments that are functions.
If you used LINQ, you have experience with a rich library where the `Func` types are part of the API set. (If you aren't familiar with LINQ, you probably want to read [the LINQ tutorial](/dotnet/csharp/linq/) and the article about [lambda expressions](../../language-reference/operators/lambda-expressions.md) before this one.) Expression Trees provide richer interaction with the arguments that are functions.

You write function arguments, typically using Lambda Expressions, when you create LINQ queries. In a typical LINQ query, those function arguments are transformed into a delegate the compiler creates.

You've likely already written code that uses Expression trees. Entity Framework's LINQ APIs accept Expression trees as the arguments for the LINQ Query Expression Pattern. That enables [Entity Framework](/ef/) to translate the query you wrote in C# into SQL that executes in the database engine. Another example is [Moq](https://github.com/Moq/moq), which is a popular mocking framework for .NET.
You already write code that uses Expression trees. Entity Framework's LINQ APIs accept Expression trees as the arguments for the LINQ Query Expression Pattern. That enables [Entity Framework](/ef/) to translate the query you wrote in C# into SQL that executes in the database engine. Another example is [Moq](https://github.com/Moq/moq), which is a popular mocking framework for .NET.

When you want to have a richer interaction, you need to use *Expression Trees*. Expression Trees represent code as a structure that you examine, modify, or execute. These tools give you the power to manipulate code during run time. You write code that examines running algorithms, or injects new capabilities. In more advanced scenarios, you modify running algorithms and even translate C# expressions into another form for execution in another environment.

Expand All @@ -24,8 +24,6 @@ You can have the C# or Visual Basic compiler create an expression tree for you b

When a lambda expression is assigned to a variable of type <xref:System.Linq.Expressions.Expression%601>, the compiler emits code to build an expression tree that represents the lambda expression.

The C# compiler generates expression trees only from expression lambdas (or single-line lambdas). It can't parse statement lambdas (or multi-line lambdas). For more information about lambda expressions in C#, see [Lambda Expressions](../../language-reference/operators/lambda-expressions.md).

The following code examples demonstrate how to have the C# compiler create an expression tree that represents the lambda expression `num => num < 5`.

```csharp
Expand All @@ -40,11 +38,13 @@ Once you build an expression tree, you [execute the code represented by the expr

## Limitations

The C# compiler generates expression trees only from expression lambdas (or single-line lambdas). It can't parse statement lambdas (or multi-line lambdas). For more information about lambda expressions in C#, see [Lambda Expressions](../../language-reference/operators/lambda-expressions.md).

There are some newer C# language elements that don't translate well into expression trees. Expression trees can't contain `await` expressions, or `async` lambda expressions. Many of the features added in C# 6 and later don't appear exactly as written in expression trees. Instead, newer features are exposed in expression trees in the equivalent, earlier syntax, where possible. Other constructs aren't available. It means that code that interprets expression trees works the same when new language features are introduced. However, even with these limitations, expression trees do enable you to create dynamic algorithms that rely on interpreting and modifying code that is represented as a data structure. It enables rich libraries such as Entity Framework to accomplish what they do.

Expression trees won't support new expression node types. It would be a breaking change for all libraries interpreting expression trees to introduce new node types. The following list includes most C# language elements that can't be used:

- [Conditional methods](../../language-reference/preprocessor-directives.md#conditional-compilation) that have been removed
- [Conditional methods](../../language-reference/preprocessor-directives.md#conditional-compilation) removed from the output
- [`base` access](../../language-reference/keywords/base.md)
- Method group expressions, including [*address-of* (`&`)](../../language-reference/operators/pointer-related-operators.md) a method group, and anonymous method expressions
- References to [local functions](../../programming-guide/classes-and-structs/local-functions.md)
Expand All @@ -59,10 +59,10 @@ Expression trees won't support new expression node types. It would be a breaking
- Lambda expressions that have [attributes](../../language-reference/operators/lambda-expressions.md#attributes)
- [Interpolated strings](../../language-reference/tokens/interpolated.md)
- UTF-8 string conversions or [UTF-8 string literals](../../language-reference/builtin-types/reference-types.md#utf-8-string-literals)
- Method invocations using [variable arguments](../../language-reference/keywords/method-parameters.md#params-modifier), [named arguments or optional arguments](../../programming-guide/classes-and-structs/named-and-optional-arguments.md)
- Method invocations using [variable arguments](../../language-reference/keywords/method-parameters.md#params-modifier), [named arguments, or optional arguments](../../programming-guide/classes-and-structs/named-and-optional-arguments.md)
- Expressions using <xref:System.Index?displayProperty=nameWithType> or <xref:System.Range?displayProperty=nameWithType>, [index "from end" (`^`) operator](../../language-reference/operators/member-access-operators.md#index-from-end-operator-) or [range expressions (`..`)](../../language-reference/operators/member-access-operators.md#range-operator-)
- [`async` lambda expressions or `await` expressions](../../language-reference/operators/lambda-expressions.md#async-lambdas), including [`await foreach` and `await using`](../../language-reference/operators/await.md#asynchronous-streams-and-disposables)
- [Tuple literals, tuple conversions, tuple `==` or `!=`, or `with` expressions](../../language-reference/builtin-types/value-tuples.md)
- [Discards (`_`)](../../fundamentals/functional/discards.md), [deconstructing assignment](../../fundamentals/functional/deconstruct.md), [pattern matching `is` operator or the pattern matching `switch` expression](../../language-reference/operators/patterns.md)
- [Discards (`_`)](../../fundamentals/functional/discards.md), [deconstructing assignment](../../fundamentals/functional/deconstruct.md), [pattern matching `is` operator, or the pattern matching `switch` expression](../../language-reference/operators/patterns.md)
- COM call with `ref` omitted on the arguments
- [`ref`](../../language-reference/keywords/ref.md), [`in`](../../language-reference/keywords/method-parameters.md#in-parameter-modifier) or [`out`](../../language-reference/keywords/method-parameters.md#out-parameter-modifier) parameters, `ref` return values, `out` arguments, or any values of [`ref struct` type](../../language-reference/builtin-types/ref-struct.md)
10 changes: 10 additions & 0 deletions docs/csharp/linq/includes/linq-syntax.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
author: BillWagner
ms.author: wiwagn
ms.topic: include
ms.date: 05/29/2024
---

> [!IMPORTANT]
>
> These samples use an <xref:System.Collections.Generic.IEnumerable%601?displayProperty=nameWithType> data source. Data sources based on <xref:System.Linq.IQueryProvider?displayProperty=nameWithType> use <xref:System.Linq.IQueryable%601?displayProperty=nameWithType> data sources and [expression trees](../../advanced-topics/expression-trees/index.md). Expression trees have [limitations](../../advanced-topics/expression-trees/index.md#limitations) on the allowed C# syntax. Furthermore, each `IQueryProvider` data source, such as [EF Core](/ef/core/querying/complex-query-operators) may impose more restrictions. Check the documentation for your data source.
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
---
title: "Converting Data Types"
description: Conversion methods change the type of input objects. See conversion operations in LINQ queries in C#, such as Enumerable.AsEnumerable and Enumerable.OfType.
ms.date: 02/14/2024
ms.date: 05/29/2024
---
# Converting Data Types (C#)

Conversion methods change the type of input objects.

[!INCLUDE [Prerequisites](../includes/linq-syntax.md)]

Conversion operations in LINQ queries are useful in various applications. Following are some examples:

- The <xref:System.Linq.Enumerable.AsEnumerable%2A?displayProperty=nameWithType> method can be used to hide a type's custom implementation of a standard query operator.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
---
title: "Filtering Data with LINQ"
description: Filtering, also known as selection, restricts results based on a condition. Learn about the standard query operator methods in LINQ in C# that perform filtering.
ms.date: 02/14/2024
ms.date: 05/29/2024
---
# Filtering Data in C# with LINQ

Filtering refers to the operation of restricting the result set to contain only those elements that satisfy a specified condition. It's also referred to as *selecting* elements that match the specified condition.

[!INCLUDE [Prerequisites](../includes/linq-syntax.md)]

The following illustration shows the results of filtering a sequence of characters. The predicate for the filtering operation specifies that the character must be 'A'.

:::image type="content" source="./media/filtering-data/linq-filter-operation.png" alt-text="Diagram that shows a LINQ filtering operation":::
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
---
title: "Grouping Data"
description: Grouping puts data into groups of elements that share an attribute. Learn about the standard query operator methods in LINQ in C# that group data elements.
ms.date: 02/16/2024
ms.date: 05/29/2024
---
# Grouping Data (C#)

Grouping refers to the operation of putting data into groups so that the elements in each group share a common attribute. The following illustration shows the results of grouping a sequence of characters. The key for each group is the character.

:::image type="content" source="./media/grouping-data/linq-group-operation.png" alt-text="Diagram that shows a LINQ Grouping operation":::

[!INCLUDE [Prerequisites](../includes/linq-syntax.md)]

The standard query operator methods that group data elements are listed in the following table.

|Method Name|Description|C# Query Expression Syntax|More Information|
Expand Down
4 changes: 3 additions & 1 deletion docs/csharp/linq/standard-query-operators/index.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
---
title: "Standard Query Operators Overview"
description: The LINQ standard query operators provide query capabilities including filtering, projection, aggregation, and sorting in C#.
ms.date: 02/16/2024
ms.date: 05/29/2024
---
# Standard Query Operators Overview

The *standard query operators* are the keywords and methods that form the LINQ pattern. The C# language defines [LINQ query keywords](../../language-reference/keywords/query-keywords.md) that you use for the most common query expression. The compiler translates expressions using these keywords to the equivalent method calls. The two forms are synonymous. Other methods that are part of the <xref:System.Linq?displayProperty=fullName> namespace don't have equivalent query keywords. In those cases, you must use the method syntax. This section covers all the query operator keywords. The runtime and other NuGet packages add more methods designed to work with LINQ queries each release. The most common methods, including those that have query keyword equivalents are covered in this section. For the full list of query methods supported by the .NET Runtime, see the <xref:System.Linq.Enumerable?displayProperty=fullName> API documentation. In addition to the methods covered here, this class contains methods for concatenating data sources, computing a single value from a data source, such as a sum, average, or other value.

[!INCLUDE [Prerequisites](../includes/linq-syntax.md)]

Most of these methods operate on sequences, where a sequence is an object whose type implements the <xref:System.Collections.Generic.IEnumerable%601> interface or the <xref:System.Linq.IQueryable%601> interface. The standard query operators provide query capabilities including filtering, projection, aggregation, sorting and more. The methods that make up each set are static members of the <xref:System.Linq.Enumerable> and <xref:System.Linq.Queryable> classes, respectively. They're defined as [*extension methods*](../../programming-guide/classes-and-structs/extension-methods.md) of the type that they operate on.

The distinction between <xref:System.Collections.Generic.IEnumerable%601> and <xref:System.Linq.IQueryable%601> sequences determines how the query is executed at runtime.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
---
title: "Join Operations"
description: A join of two data sources associates objects with objects that share an attribute across data sources. Learn about join methods in the LINQ framework in C#.
ms.date: 02/16/2024
ms.date: 05/29/2024
no-loc: [Join, GroupJoin]
---
# Join Operations in LINQ

A *join* of two data sources is the association of objects in one data source with objects that share a common attribute in another data source.

[!INCLUDE [Prerequisites](../includes/linq-syntax.md)]

Joining is an important operation in queries that target data sources whose relationships to each other can't be followed directly. In object-oriented programming, joining could mean a correlation between objects that isn't modeled, such as the backwards direction of a one-way relationship. An example of a one-way relationship is a `Student` class that has a property of type `Department` that represents the major, but the `Department` class doesn't have a property that is a collection of `Student` objects. If you have a list of `Department` objects and you want to find all the students in each department, you could use a join operation to find them.

The join methods provided in the LINQ framework are <xref:System.Linq.Enumerable.Join%2A> and <xref:System.Linq.Enumerable.GroupJoin%2A>. These methods perform equijoins, or joins that match two data sources based on equality of their keys. (For comparison, Transact-SQL supports join operators other than `equals`, for example the `less than` operator.) In relational database terms, <xref:System.Linq.Enumerable.Join%2A> implements an inner join, a type of join in which only those objects that have a match in the other data set are returned. The <xref:System.Linq.Enumerable.GroupJoin%2A> method has no direct equivalent in relational database terms, but it implements a superset of inner joins and left outer joins. A left outer join is a join that returns each element of the first (left) data source, even if it has no correlated elements in the other data source.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
---
title: "Partitioning data"
description: Learn how to partition data in LINQ. View an illustration showing the results of partitioning operations.
ms.date: 02/14/2024
ms.date: 05/29/2024
---
# Partitioning data (C#)

Partitioning in LINQ refers to the operation of dividing an input sequence into two sections, without rearranging the elements, and then returning one of the sections.

[!INCLUDE [Prerequisites](../includes/linq-syntax.md)]

The following illustration shows the results of three different partitioning operations on a sequence of characters. The first operation returns the first three elements in the sequence. The second operation skips the first three elements and returns the remaining elements. The third operation skips the first two elements in the sequence and returns the next three elements.

:::image type="content" source="./media/partitioning-data/linq-partitioning-operations.png" alt-text="Illustration that shows three LINQ partitioning operations.":::
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
---
title: "Projection operations in LINQ"
description: Learn about projection operations. These operations transform an object into a new form that often consists only of properties used later.
ms.date: 02/14/2024
ms.date: 05/29/2024
---
# Projection operations (C#)

Projection refers to the operation of transforming an object into a new form that often consists only of those properties subsequently used. By using projection, you can construct a new type that is built from each object. You can project a property and perform a mathematical function on it. You can also project the original object without changing it.

[!INCLUDE [Prerequisites](../includes/linq-syntax.md)]

The standard query operator methods that perform projection are listed in the following section.

## Methods
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@
title: "Quantifier Operations"
titleSuffix: LINQ
description: Learn about quantifier operations in LINQ. These methods, `All`, `Any`, and `Contains`, return a Boolean value indicating whether some or all elements in a sequence satisfy a condition.
ms.date: 02/14/2024
ms.date: 05/29/2024
---
# Quantifier operations in LINQ (C#)

Quantifier operations return a <xref:System.Boolean> value that indicates whether some or all of the elements in a sequence satisfy a condition.

[!INCLUDE [Prerequisites](../includes/linq-syntax.md)]

The following illustration depicts two different quantifier operations on two different source sequences. The first operation asks if any of the elements are the character 'A'. The second operation asks if all the elements are the character 'A'. Both methods return `true` in this example.

:::image type="content" source="./media/quantifier-operations/linq-quantifier-operations.png" alt-text="LINQ Quantifier Operations":::
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
---
title: "Set operations"
description: Learn about set operations and the standard query operator methods that perform set operations in LINQ in C#.
ms.date: 01/22/2024
ms.date: 05/29/2024
---
# Set operations (C#)

Set operations in LINQ refer to query operations that produce a result set based on the presence or absence of equivalent elements within the same or separate collections.

[!INCLUDE [Prerequisites](../includes/linq-syntax.md)]

| Method names | Description | C# query expression syntax | More information |
|--|--|--|--|
| `Distinct` or `DistinctBy` | Removes duplicate values from a collection. | Not applicable. | <xref:System.Linq.Enumerable.Distinct%2A?displayProperty=nameWithType><br /><xref:System.Linq.Enumerable.DistinctBy%2A?displayProperty=nameWithType><br /><xref:System.Linq.Queryable.Distinct%2A?displayProperty=nameWithType><br /><xref:System.Linq.Queryable.DistinctBy%2A?displayProperty=nameWithType> |
Expand Down
Loading