You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/csharp/asynchronous-programming/async-return-types.md
+8-8Lines changed: 8 additions & 8 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -19,14 +19,14 @@ For more information about async methods, see [Asynchronous programming with asy
19
19
Several other types also exist that are specific to Windows workloads:
20
20
21
21
-<xref:System.Windows.Threading.DispatcherOperation>, for async operations limited to Windows.
22
-
-<xref:Windows.Foundation.IAsyncAction>, for async actions in UWP that don't return a value.
23
-
-<xref:Windows.Foundation.IAsyncActionWithProgress%601>, for async actions in UWP that report progress but don't return a value.
24
-
-<xref:Windows.Foundation.IAsyncOperation%601>, for async operations in UWP that return a value.
25
-
-<xref:Windows.Foundation.IAsyncOperationWithProgress%602>, for async operations in UWP that report progress and return a value.
22
+
-<xref:Windows.Foundation.IAsyncAction>, for async actions in Universal Windows Platform (UWP) apps that don't return a value.
23
+
-<xref:Windows.Foundation.IAsyncActionWithProgress%601>, for async actions in UWP apps that report progress but don't return a value.
24
+
-<xref:Windows.Foundation.IAsyncOperation%601>, for async operations in UWP apps that return a value.
25
+
-<xref:Windows.Foundation.IAsyncOperationWithProgress%602>, for async operations in UWP apps that report progress and return a value.
26
26
27
27
## Task return type
28
28
29
-
Async methods that don't contain a `return` statement or that contain a `return` statement that doesn't return an operand usually have a return type of <xref:System.Threading.Tasks.Task>. Such methods return `void` if they run synchronously. If you use a <xref:System.Threading.Tasks.Task> return type for an async method, a calling method can use an `await` operator to suspend the caller's completion until the called async method has finished.
29
+
Async methods that don't contain a `return` statement or that contain a `return` statement that doesn't return an operand usually have a return type of <xref:System.Threading.Tasks.Task>. Such methods return `void` if they run synchronously. If you use a <xref:System.Threading.Tasks.Task> return type for an async method, a calling method can use an `await` operator to suspend the caller's completion until the called async method finishes.
30
30
31
31
In the following example, the `WaitAndApologizeAsync` method doesn't contain a `return` statement, so the method returns a <xref:System.Threading.Tasks.Task> object. Returning a `Task` enables `WaitAndApologizeAsync` to be awaited. The <xref:System.Threading.Tasks.Task> type doesn't include a `Result` property because it has no return value.
32
32
@@ -48,7 +48,7 @@ In the following example, the `GetLeisureHoursAsync` method contains a `return`
When `GetLeisureHoursAsync` is called from within an await expression in the `ShowTodaysInfo` method, the await expression retrieves the integer value (the value of `leisureHours`) that's stored in the task returned by the `GetLeisureHours` method. For more information about await expressions, see [await](../language-reference/operators/await.md).
51
+
When `GetLeisureHoursAsync` is called from within an await expression in the `ShowTodaysInfo` method, the await expression retrieves the integer value (the value of `leisureHours`) stored in the task returned by the `GetLeisureHours` method. For more information about await expressions, see [await](../language-reference/operators/await.md).
52
52
53
53
You can better understand how `await` retrieves the result from a `Task<T>` by separating the call to `GetLeisureHoursAsync` from the application of `await`, as the following code shows. A call to method `GetLeisureHoursAsync` that isn't immediately awaited returns a `Task<int>`, as you would expect from the declaration of the method. The task is assigned to the `getLeisureHoursTask` variable in the example. Because `getLeisureHoursTask` is a <xref:System.Threading.Tasks.Task%601>, it contains a <xref:System.Threading.Tasks.Task%601.Result> property of type `TResult`. In this case, `TResult` represents an integer type. When `await` is applied to `getLeisureHoursTask`, the await expression evaluates to the contents of the <xref:System.Threading.Tasks.Task%601.Result%2A> property of `getLeisureHoursTask`. The value is assigned to the `ret` variable.
54
54
@@ -73,7 +73,7 @@ The following example shows the behavior of an async event handler. In the examp
73
73
74
74
An async method can return any type that has an accessible `GetAwaiter` method that returns an instance of an *awaiter type*. In addition, the type returned from the `GetAwaiter` method must have the <xref:System.Runtime.CompilerServices.AsyncMethodBuilderAttribute?displayProperty=nameWithType> attribute. You can learn more in the article on [Attributes read by the compiler](../language-reference/attributes/general.md#asyncmethodbuilder-attribute) or the C# spec for the [Task type builder pattern](~/_csharpstandard/standard/classes.md#15152-task-type-builder-pattern).
75
75
76
-
This feature is the complement to [awaitable expressions](~/_csharpstandard/standard/expressions.md#12982-awaitable-expressions), which describes the requirements for the operand of `await`. Generalized async return types enable the compiler to generate `async` methods that return different types. Generalized async return types enabled performance improvements in the .NET libraries. Because <xref:System.Threading.Tasks.Task> and <xref:System.Threading.Tasks.Task%601> are reference types, memory allocation in performance-critical paths, particularly when allocations occur in tight loops, can adversely affect performance. Support for generalized return types means that you can return a lightweight value type instead of a reference type to avoid additional memory allocations.
76
+
This feature is the complement to [awaitable expressions](~/_csharpstandard/standard/expressions.md#12982-awaitable-expressions), which describes the requirements for the operand of `await`. Generalized async return types enable the compiler to generate `async` methods that return different types. Generalized async return types enabled performance improvements in the .NET libraries. Because <xref:System.Threading.Tasks.Task> and <xref:System.Threading.Tasks.Task%601> are reference types, memory allocation in performance-critical paths, particularly when allocations occur in tight loops, can adversely affect performance. Support for generalized return types means that you can return a lightweight value type instead of a reference type to avoid more memory allocations.
77
77
78
78
.NET provides the <xref:System.Threading.Tasks.ValueTask%601?displayProperty=nameWithType> structure as a lightweight implementation of a generalized task-returning value. The following example uses the <xref:System.Threading.Tasks.ValueTask%601> structure to retrieve the value of two dice rolls.
79
79
@@ -85,7 +85,7 @@ You can apply the `AsyncMethodBuilder` attribute to an async method (instead of
85
85
86
86
## Async streams with IAsyncEnumerable\<T\>
87
87
88
-
An async method may return an *async stream*, represented by <xref:System.Collections.Generic.IAsyncEnumerable%601>. An async stream provides a way to enumerate items read from a stream when elements are generated in chunks with repeated asynchronous calls. The following example shows an async method that generates an async stream:
88
+
An async method might return an *async stream*, represented by <xref:System.Collections.Generic.IAsyncEnumerable%601>. An async stream provides a way to enumerate items read from a stream when elements are generated in chunks with repeated asynchronous calls. The following example shows an async method that generates an async stream:
You can't specify a specific type outside the parentheses even if every field in the tuple has the
49
-
same type. Doing so generates compiler error CS8136, "Deconstruction 'var (...)' form disallows a specific type for 'var'.".
49
+
same type. Doing so generates compiler error CS8136, "Deconstruction 'var (...)' form disallows a specific type for 'var'."
50
50
51
51
You must assign each element of the tuple to a variable. If you omit any elements, the compiler generates error CS8132, "Can't deconstruct a tuple of 'x' elements into 'y' variables."
52
52
53
53
## Tuple elements with discards
54
54
55
-
Often when deconstructing a tuple, you're interested in the values of only some elements. You can take advantage of C#'s support for *discards*, which are write-only variables whose values you've chosen to ignore. A discard is chosen by an underscore character ("\_") in an assignment. You can discard as many values as you like; all are represented by the single discard, `_`.
55
+
Often when deconstructing a tuple, you're interested in the values of only some elements. You can take advantage of C#'s support for *discards*, which are write-only variables whose values you chose to ignore. You declare a discard with an underscore character ("\_") in an assignment. You can discard as many values as you like; a single discard, `_`, represents all the discarded values.
56
56
57
57
The following example illustrates the use of tuples with discards. The `QueryCityDataForYears` method returns a six-tuple with the name of a city, its area, a year, the city's population for that year, a second year, and the city's population for that second year. The example shows the change in population between those two years. Of the data available from the tuple, we're unconcerned with the city area, and we know the city name and the two dates at design-time. As a result, we're only interested in the two population values stored in the tuple, and can handle its remaining values as discards.
C# doesn't offer built-in support for deconstructing non-tuple types other than the [`record`](#record-types) and [DictionaryEntry](xref:System.Collections.DictionaryEntry.Deconstruct%2A) types. However, as the author of a class, a struct, or an interface, you can allow instances of the type to be deconstructed by implementing one or more `Deconstruct` methods. The method returns void, and each value to be deconstructed is indicated by an [out](../../language-reference/keywords/method-parameters.md#out-parameter-modifier) parameter in the method signature. For example, the following `Deconstruct` method of a `Person` class returns the first, middle, and last name:
63
+
C# offers built-in support for deconstructing tuple types, [`record`](#record-types), and [DictionaryEntry](xref:System.Collections.DictionaryEntry.Deconstruct%2A) types. However, as the author of a class, a struct, or an interface, you can allow instances of the type to be deconstructed by implementing one or more `Deconstruct` methods. The method returns void. An [out](../../language-reference/keywords/method-parameters.md#out-parameter-modifier) parameter in the method signature represents each value to be deconstructed. For example, the following `Deconstruct` method of a `Person` class returns the first, middle, and family name:
@@ -70,44 +70,36 @@ You can then deconstruct an instance of the `Person` class named `p` with an ass
70
70
71
71
The following example overloads the `Deconstruct` method to return various combinations of properties of a `Person` object. Individual overloads return:
72
72
73
-
- A first and last name.
74
-
- A first, middle, and last name.
75
-
- A first name, a last name, a city name, and a state name.
73
+
- A first and family name.
74
+
- A first, middle, and family name.
75
+
- A first name, a family name, a city name, and a state name.
Multiple `Deconstruct` methods having the same number of parameters are ambiguous. You must be careful to define `Deconstruct` methods with different numbers of parameters, or "arity". `Deconstruct` methods with the same number of parameters cannot be distinguished during overload resolution.
79
+
Multiple `Deconstruct` methods having the same number of parameters are ambiguous. You must be careful to define `Deconstruct` methods with different numbers of parameters, or "arity". `Deconstruct` methods with the same number of parameters can't be distinguished during overload resolution.
80
80
81
81
## User-defined type with discards
82
82
83
-
Just as you do with [tuples](#tuple-elements-with-discards), you can use discards to ignore selected items returned by a `Deconstruct` method. Each discard is defined by a variable named "\_", and a single deconstruction operation can include multiple discards.
83
+
Just as you do with [tuples](#tuple-elements-with-discards), you can use discards to ignore selected items returned by a `Deconstruct` method. A variable named "\_" represents a discard. A single deconstruction operation can include multiple discards.
84
84
85
-
The following example deconstructs a `Person` object into four strings (the first and last names, the city, and the state) but discards the last name and the state.
85
+
The following example deconstructs a `Person` object into four strings (the first and family names, the city, and the state) but discards the family name and the state.
If you didn't author a class, struct, or interface, you can still deconstruct objects of that type by implementing one or more `Deconstruct`[extension methods](../../programming-guide/classes-and-structs/extension-methods.md) to return the values in which you're interested.
92
92
93
-
The following example defines two `Deconstruct` extension methods for the <xref:System.Reflection.PropertyInfo?displayProperty=nameWithType> class. The first returns a set of values that indicate the characteristics of the property, including its type, whether it's static or instance, whether it's read-only, and whether it's indexed. The second indicates the property's accessibility. Because the accessibility of get and set accessors can differ, Boolean values indicate whether the property has separate get and set accessors and, if it does, whether they have the same accessibility. If there's only one accessor or both the get and the set accessor have the same accessibility, the `access` variable indicates the accessibility of the property as a whole. Otherwise, the accessibility of the get and set accessors are indicated by the `getAccess` and `setAccess` variables.
93
+
The following example defines two `Deconstruct` extension methods for the <xref:System.Reflection.PropertyInfo?displayProperty=nameWithType> class. The first returns a set of values that indicate the characteristics of the property. The second indicates the property's accessibility. Boolean values indicate whether the property has separate get and set accessors or different accessibility. If there's only one accessor or both the get and the set accessor have the same accessibility, the `access` variable indicates the accessibility of the property as a whole. Otherwise, the accessibility of the get and set accessors are indicated by the `getAccess` and `setAccess` variables.
Some system types provide the `Deconstruct` method as a convenience. For example, the <xref:System.Collections.Generic.KeyValuePair%602?displayProperty=nameWithType> type provides this functionality. When you're iterating over a <xref:System.Collections.Generic.Dictionary%602?displayProperty=nameWithType> each element is a `KeyValuePair<TKey, TValue>` and can be deconstructed. Consider the following example:
99
+
Some system types provide the `Deconstruct` method as a convenience. For example, the <xref:System.Collections.Generic.KeyValuePair%602?displayProperty=nameWithType> type provides this functionality. When you're iterating over a <xref:System.Collections.Generic.Dictionary%602?displayProperty=nameWithType>, each element is a `KeyValuePair<TKey, TValue>` and can be deconstructed. Consider the following example:
This extension method allows all <xref:System.Nullable%601> types to be deconstructed into a tuple of `(bool hasValue, T value)`. The following example shows code that uses this extension method:
When you declare a [record](../../language-reference/builtin-types/record.md) type by using two or more positional parameters, the compiler creates a `Deconstruct` method with an `out` parameter for each positional parameter in the `record` declaration. For more information, see [Positional syntax for property definition](../../language-reference/builtin-types/record.md#positional-syntax-for-property-definition) and [Deconstructor behavior in derived records](../../language-reference/builtin-types/record.md#deconstructor-behavior-in-derived-records).
0 commit comments