Skip to content
Draft
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
9 changes: 9 additions & 0 deletions standard/conversions.md
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,15 @@

There is an implicit conversion from a *switch_expression* ([§12.11](expressions.md#1211-switch-expression)) to every type `T` for which there exists an implicit conversion from each *switch_expression_arm*’s *switch_expression_arm_expression*’s to `T`.

### §imp-cond-expr-conv Implicit conditional expression conversions

For a *conditional_expression* `c ? e1 : e2`, when

1. there is no common type for `e1` and `e2`, or
1. for which a common type exists, but one of the expressions `e1` or `e2` has no implicit conversion to that type

an implicit ***conditional expression conversion*** exists that permits an implicit conversion from *conditional_expression* to any type `T` for which there is a conversion-from-expression from `e1` to `T` and also from `e2` to `T`. It is an error if *conditional_expression* neither has a common type between `e1` and `e2` nor is subject to a conditional expression conversion.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this makes available a conversion to a specific type... and I'm assuming we expect the rules to just drop out for which types are "tested" for this? For example, if I have

void M(int x) { ... }
void M(string y) { ... }

... then overload resolution of M(true ? new(new char[0]) : new(new char[1])) would detect that there's an implicit conversion from both of those target-typed new expressions to string, but not to int?


## 10.3 Explicit conversions

### 10.3.1 General
Expand Down Expand Up @@ -803,7 +812,7 @@
>
> var amt6 = 66036; // var types amt6 as int
> var dose6 = (Dose)amt6; // amt3 is int, int to ushort conversion added
> // warning as information loss may occur

Check warning on line 815 in standard/conversions.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/conversions.md#L815

MDC032::Line length 82 > maximum 81
> Console.WriteLine(dose6); // outputs 500mg, not 66036mg, due to information loss
>
> // Using a constructor instead of user-defined conversion:
Expand Down
9 changes: 5 additions & 4 deletions standard/expressions.md
Original file line number Diff line number Diff line change
Expand Up @@ -1111,10 +1111,11 @@

#### 12.6.4.5 Better conversion from expression

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:
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 `E` does not exactly match `T₂` and at least one of the following holds:

- `E` exactly matches `T₁` and `E` does not exactly match `T₂` ([§12.6.4.6](expressions.md#12646-exactly-matching-expression))
- `E` exactly matches both or neither of `T₁` and `T₂`, and `T₁` is a better conversion target than `T₂` ([§12.6.4.7](expressions.md#12647-better-conversion-target))
- `C₁` is not a conditional expression conversion and `C₂` is a conditional expression conversion.
- `E` exactly matches both or neither of `T₁` and `T₂`, and `T₁` is a better conversion target than `T₂` ([§12.6.4.7](expressions.md#12647-better-conversion-target)) and either `C₁` and `C₂` are both conditional expression conversions or neither is a conditional expression conversion.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I need to figure out what this is about - but E can't exactly match T2 given line 1113, so it can't match both T1 and T2...

- `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₂`

#### 12.6.4.6 Exactly matching expression
Expand Down Expand Up @@ -1629,7 +1630,7 @@
> These two examples demonstrate the purpose of the qualification on the first case above – it allows implicit constant conversions ([§10.2.11](conversions.md#10211-implicit-constant-expression-conversions)). The type of the tuple literal is `(int, long)`. There is no implicit conversion from `int` to `short`, but there is one from the constant `1` to short. The first example involves an implicit conversion replacing the tuple literal’s inherent type. In the second example, which does not involve an implicit conversion, the tuple literal is reclassified as a value based on its inherent type.
>
> <!-- Example: {template:"standalone-console-without-using", name:"TupleExpressions1", expectedErrors:["CS0815"], ignoredWarnings:["CS0219"]} -->
> ```csharp

Check warning on line 1633 in standard/expressions.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/expressions.md#L1633

MDC032::Line length 83 > maximum 81
> (long l, string) t1 = (l: 1, null); // literal has no type, use implicit conversion
> var t2 = (i: 2, "Two"); // (int i, string)
> var t3 = (i: 3, null); // Error: no type
Expand Down Expand Up @@ -2152,8 +2153,8 @@
A *null_conditional_invocation_expression* is syntactically either a *null_conditional_member_access* ([§12.8.8](expressions.md#1288-null-conditional-member-access)) or *null_conditional_element_access* ([§12.8.13](expressions.md#12813-null-conditional-element-access)) where the final *dependent_access* is an invocation expression ([§12.8.10](expressions.md#12810-invocation-expressions)).

A *null_conditional_invocation_expression* occurs within the context of a *statement_expression* ([§13.7](statements.md#137-expression-statements)), *anonymous_function_body* ([§12.21.1](expressions.md#12211-general)), or *method_body* ([§15.6.1](classes.md#1561-general)).

Check warning on line 2156 in standard/expressions.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/expressions.md#L2156

MDC032::Line length 84 > maximum 81
Unlike the syntactically equivalent *null_conditional_member_access* or *null_conditional_element_access*, a *null_conditional_invocation_expression* may be classified as nothing.

Check warning on line 2157 in standard/expressions.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/expressions.md#L2157

MDC032::Line length 85 > maximum 81

```ANTLR
null_conditional_invocation_expression
Expand Down Expand Up @@ -2233,7 +2234,7 @@
- The *primary_expression* has compile-time type `dynamic`.
- At least one expression of the *argument_list* has compile-time type `dynamic`.

In this case the compile-time type of the *element_access* depends on the compile-time type of its *primary_expression*: if it has an array type then the compile-time type is the element type of that array type; otherwise the compile-time type is `dynamic` and the *element_access* is classified as a value of type `dynamic`. The rules below to determine the meaning of the *element_access* are then applied at run-time, using the run-time type instead of the compile-time type of those of the *primary_expression* and *argument_list* expressions which have the compile-time type `dynamic`. If the *primary_expression* does not have compile-time type `dynamic`, then the element access undergoes a limited compile-time check as described in [§12.6.5](expressions.md#1265-compile-time-checking-of-dynamic-member-invocation).

Check warning on line 2237 in standard/expressions.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/expressions.md#L2237

MDC032::Line length 82 > maximum 81

> *Example*:
>
Expand Down Expand Up @@ -3371,7 +3372,7 @@
- one of the following value types: `sbyte`, `byte`, `short`, `ushort`, `int`, `uint`, `long`, `ulong`, `char`, `float`, `double`, `decimal`, `bool,`; or
- any enumeration type.

### 12.8.22 Stack allocation

Check warning on line 3375 in standard/expressions.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/expressions.md#L3375

MDC032::Line length 86 > maximum 81

A stack allocation expression allocates a block of memory from the execution stack. The ***execution stack*** is an area of memory where local variables are stored. The execution stack is not part of the managed heap. The memory used for local variable storage is automatically recovered when the current function returns.

Expand Down Expand Up @@ -3735,7 +3736,7 @@
;
```

A *cast_expression* of the form `(T)E`, where `T` is a type and `E` is a *unary_expression*, performs an explicit conversion ([§10.3](conversions.md#103-explicit-conversions)) of the value of `E` to type `T`. If no explicit conversion exists from `E` to `T`, a binding-time error occurs. Otherwise, the result is the value produced by the explicit conversion. The result is always classified as a value, even if `E` denotes a variable.
A *cast_expression* of the form `(T)E`, where `T` is a type and `E` is a *unary_expression*, performs an explicit conversion ([§10.3](conversions.md#103-explicit-conversions)) of the value of `E` to type `T`. In the presence of a conditional expression conversion (§imp-cond-expr-conv) there may be more than one possible conversion from `E` to `T`, in which case, the conditional expression conversion shall only be used as a last resort. If no explicit conversion exists from `E` to `T`, a binding-time error occurs. Otherwise, the result is the value produced by the explicit conversion. The result is always classified as a value, even if `E` denotes a variable.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm confused about this and think it would benefit from an example.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


The grammar for a *cast_expression* leads to certain syntactic ambiguities.

Expand Down Expand Up @@ -5204,7 +5205,7 @@
If `ref` is not present, the second and third operands, `x` and `y`, of the `?:` operator control the type of the conditional expression:

- If `x` has type `X` and `y` has type `Y` then,
- If an identity conversion exists between `X` and `Y`, then the result is the best common type of a set of expressions ([§12.6.3.16](expressions.md#126316-finding-the-best-common-type-of-a-set-of-expressions)). If either type is `dynamic`, type inference prefers `dynamic` ([§8.7](types.md#87-the-dynamic-type)). If either type is a tuple type ([§8.3.11](types.md#8311-tuple-types)), type inference includes the element names when the element names in the same ordinal position match in both tuples.
- If an identity conversion exists between `X` and `Y`, then the result is the best common type of a set of expressions ([§12.6.3.16](expressions.md#126316-finding-the-best-common-type-of-a-set-of-expressions)). ***placeholder for words somehow referring to “12.6.4.5 Better conversion from expression.”*** If either type is `dynamic`, type inference prefers `dynamic` ([§8.7](types.md#87-the-dynamic-type)). If either type is a tuple type ([§8.3.11](types.md#8311-tuple-types)), type inference includes the element names when the element names in the same ordinal position match in both tuples.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm hoping @BillWagner can provide motivation for this via an example.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

- Otherwise, if an implicit conversion ([§10.2](conversions.md#102-implicit-conversions)) exists from `X` to `Y`, but not from `Y` to `X`, then `Y` is the type of the conditional expression.
- Otherwise, if an implicit enumeration conversion ([§10.2.4](conversions.md#1024-implicit-enumeration-conversions)) exists from `X` to `Y`, then `Y` is the type of the conditional expression.
- Otherwise, if an implicit enumeration conversion ([§10.2.4](conversions.md#1024-implicit-enumeration-conversions)) exists from `Y` to `X`, then `X` is the type of the conditional expression.
Expand Down Expand Up @@ -6937,7 +6938,7 @@
<!-- markdownlint-disable MD028 -->

<!-- markdownlint-enable MD028 -->
> *Note*: The construction of intermediate tuples produced by this algorithm might be elided by an implementation as specified by [§8.3.11.2](types.md#83112-eliding-intermediate-tuple-creation). *end note*

Check warning on line 6941 in standard/expressions.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/expressions.md#L6941

MDC032::Line length 82 > maximum 81

#### 12.23.3.2 Abridged deconstructors

Expand Down Expand Up @@ -6978,7 +6979,7 @@
> ```csharp
> var (a, b, (c, d, (e, f))) = (1, 2, (3, 4, (5, 6)));
> ```
>

Check warning on line 6982 in standard/expressions.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/expressions.md#L6982

MDC032::Line length 82 > maximum 81
> In this example, notice that the structure of nested tuples must match on both sides of the assignment.
>
> If any variable(s) on the left side are implicitly typed, the corresponding expression(s) must have a type:
Expand Down Expand Up @@ -7024,7 +7025,7 @@
> *Example*: Here are some examples of using `= ref`:
>
> <!-- Example: {template:"code-in-class-lib-without-using", name:"RefAssignment", replaceEllipsis:true, customEllipsisReplacements: ["return 0;","int[] vals = new int[2]; return ref vals[0];","uint[] vals = new uint[2]; return ref vals[0];","int[] vals = new int[2]; return ref vals[0];"], expectedErrors:["CS1510","CS8173","CS8331"]} -->
> ```csharp

Check warning on line 7028 in standard/expressions.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/expressions.md#L7028

MDC032::Line length 82 > maximum 81
> public static int M1() { ... }
> public static ref int M2() { ... }
> public static ref uint M2u() { ... }
Expand Down
Loading