From 30a422bc5eb3861a664e54949737efb9730edffc Mon Sep 17 00:00:00 2001 From: Rex Jaeschke Date: Tue, 11 Aug 2026 16:31:13 -0400 Subject: [PATCH 1/2] add support for Better conversion --- standard/expressions.md | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/standard/expressions.md b/standard/expressions.md index 404efedd5..f2517be9e 100644 --- a/standard/expressions.md +++ b/standard/expressions.md @@ -1183,10 +1183,7 @@ Given `int i = 10;`, according to [§12.6.4.2](expressions.md#12642-applicable-f Given an implicit conversion `C₁` that converts from an expression `E` to a type `T₁`, and an implicit conversion `C₂` that converts from an expression `E` to a type `T₂`, `C₁` is a ***better conversion*** than `C₂` if one of the following holds: -- `E` is a *collection_expression* and one of the following holds: - - `T₁` is `System.ReadOnlySpan`, and `T₂` is `System.Span`, and an implicit conversion exists from `E₁` to `E₂`. - - `T₁` is `System.ReadOnlySpan` or `System.Span`, and `T₂` is an *array_type*, or one of the following interface types implemented by an *array_type*: `System.Collections.Generic.IEnumerable`, `System.Collections.Generic.IReadOnlyCollection`, `System.Collections.Generic.IReadOnlyList`, `System.Collections.Generic.ICollection`, or `System.Collections.Generic.IList` with element type `E₂`, and an implicit conversion exists from `E₁` to `E₂`. - - `T₁` and `T₂` are not `System.ReadOnlySpan` or `System.Span`, and an implicit conversion exists from `T₁` to `T₂`. +- `E` is a *collection_expression* and `C₁` is a better collection conversion from expression than `C₂` (see definition below): - `E` is not a *collection_expression* and one of the following holds: - `C1` is not a *function_type_conversion* and `C2` is a *function_type_conversion*, or - `E` exactly matches `T₁` and `E` does not exactly match `T₂` ([§12.6.4.6](expressions.md#12646-exactly-matching-expression)) @@ -1196,6 +1193,34 @@ Given an implicit conversion `C₁` that converts from an expression `E` to a ty > *Note*: This is only applicable in unsafe code. *end note* - `E` is a method group ([§12.2](expressions.md#122-expression-classifications)), `T₁` is compatible ([§21.4](delegates.md#214-delegate-compatibility)) with the single best method from the method group for conversion `C₁`, and `T₂` is not compatible with the single best method from the method group for conversion `C₂` +Given the following: + +- `E` is a collection expression with element expressions `[EL₁, EL₂, ..., ELₙ]` +- `T₁` and `T₂` are collection types +- `E₁` is the element type of `T₁` +- `E₂` is the element type of `T₂` +- `CE₁ᵢ` are the series of conversions from `ELᵢ` to `E₁` +- `CE₂ᵢ` are the series of conversions from `ELᵢ` to `E₂` + +If there is an identity conversion from `E₁` to `E₂`, then the element conversions are as good as each other. Otherwise, the element conversions to `E₁` are ***better than the element conversions*** to `E₂` if: + +- For every `ELᵢ`, `CE₁ᵢ` is at least as good as `CE₂ᵢ`, and +- There is at least one i where `CE₁ᵢ` is better than `CE₂ᵢ` + +Otherwise, neither set of element conversions is better than the other, and they are also not as good as each other. + +Conversion comparisons are made using better conversion from expression if `ELᵢ` is not a spread element. If `ELᵢ` is a spread element, use better conversion from the element type of the spread collection to `E₁` or `E₂`, respectively. + +`C₁` is a ***better collection conversion from expression*** than `C₂` if: + +- Both `T₁` and `T₂` are not *span types*, and `T₁` is implicitly convertible to `T₂`, and `T₂` is not implicitly convertible to `T₁`, or +- `E₁` does not have an identity conversion to `E₂`, and the element conversions to `E₁` are ***better than the element conversions*** to `E₂`, or +- `E₁` has an identity conversion to `E₂`, and one of the following holds: + - `T₁` is `System.ReadOnlySpan`, and `T₂` is `System.Span`, or + - `T₁` is `System.ReadOnlySpan` or `System.Span`, and `T₂` is an *array_or_array_interface* with *element type* `E₂` + +Otherwise, neither collection type is better, and the result is ambiguous. + > *Example*: The following example shows the differences with overload resolution between array initializers and collection expressions: > > From 3ff0a5f7d864e57ac6aedd9f061ad678af4a6e5a Mon Sep 17 00:00:00 2001 From: Rex Jaeschke Date: Tue, 11 Aug 2026 16:39:43 -0400 Subject: [PATCH 2/2] fix md --- standard/expressions.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/standard/expressions.md b/standard/expressions.md index f2517be9e..36124aebd 100644 --- a/standard/expressions.md +++ b/standard/expressions.md @@ -1207,8 +1207,8 @@ If there is an identity conversion from `E₁` to `E₂`, then the element conve - For every `ELᵢ`, `CE₁ᵢ` is at least as good as `CE₂ᵢ`, and - There is at least one i where `CE₁ᵢ` is better than `CE₂ᵢ` -Otherwise, neither set of element conversions is better than the other, and they are also not as good as each other. - +Otherwise, neither set of element conversions is better than the other, and they are also not as good as each other. + Conversion comparisons are made using better conversion from expression if `ELᵢ` is not a spread element. If `ELᵢ` is a spread element, use better conversion from the element type of the spread collection to `E₁` or `E₂`, respectively. `C₁` is a ***better collection conversion from expression*** than `C₂` if: @@ -1216,8 +1216,8 @@ Conversion comparisons are made using better conversion from expression if `EL - Both `T₁` and `T₂` are not *span types*, and `T₁` is implicitly convertible to `T₂`, and `T₂` is not implicitly convertible to `T₁`, or - `E₁` does not have an identity conversion to `E₂`, and the element conversions to `E₁` are ***better than the element conversions*** to `E₂`, or - `E₁` has an identity conversion to `E₂`, and one of the following holds: - - `T₁` is `System.ReadOnlySpan`, and `T₂` is `System.Span`, or - - `T₁` is `System.ReadOnlySpan` or `System.Span`, and `T₂` is an *array_or_array_interface* with *element type* `E₂` + - `T₁` is `System.ReadOnlySpan`, and `T₂` is `System.Span`, or + - `T₁` is `System.ReadOnlySpan` or `System.Span`, and `T₂` is an *array_or_array_interface* with *element type* `E₂` Otherwise, neither collection type is better, and the result is ambiguous.