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
6 changes: 6 additions & 0 deletions standard/conversions.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
> ```csharp
> enum Color { Red, Blue, Green }
>
> // The expression 0 converts implicitly to enum types

Check warning on line 28 in standard/conversions.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/conversions.md#L28

MDC032::Line length 82 > maximum 81
> Color c0 = 0;
>
> // Other int expressions need explicit conversion
Expand Down Expand Up @@ -390,6 +390,12 @@

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-obj-creation-conv Implicit object-creation conversions

There is an implicit ***object-creation conversion*** from a *target_typed_new* expression ([§12.8.17.2](expressions.md#128172-object-creation-expressions)) to every type.

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.

Does this include pointer types?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

No, because a pointer type can't be used in an object creation expression. See https://github.com/dotnet/csharpstandard/blob/draft-v8/standard/expressions.md#1281721-general


Given a target type `T`, if `T` is an instance of `System.Nullable`, the type `T0` is `T`'s underlying type. Otherwise `T0` is `T`. The meaning of a *target_typed_new* expression that is converted to the type `T` is the same as the meaning of a corresponding *object_creation_expression* that specifies `T0` as the type.

## 10.3 Explicit conversions

### 10.3.1 General
Expand Down
13 changes: 11 additions & 2 deletions standard/expressions.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
# 12 Expressions

Check warning on line 1 in standard/expressions.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/expressions.md#L1

MDC032::Line length 83 > maximum 81

Check warning on line 2 in standard/expressions.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/expressions.md#L2

MDC032::Line length 84 > maximum 81
## 12.1 General

Check warning on line 3 in standard/expressions.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/expressions.md#L3

MDC032::Line length 85 > maximum 81

Check warning on line 3 in standard/expressions.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/expressions.md#L3

MDC032::Line length 86 > maximum 81

An expression is a sequence of operators and operands. This clause defines the syntax, order of evaluation of operands and operators, and meaning of expressions.

Check warning on line 5 in standard/expressions.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/expressions.md#L5

MDC032::Line length 82 > maximum 81

Check warning on line 6 in standard/expressions.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/expressions.md#L6

MDC032::Line length 82 > maximum 81

Check warning on line 6 in standard/expressions.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/expressions.md#L6

MDC032::Line length 82 > maximum 81
## 12.2 Expression classifications

### 12.2.1 General

The result of an expression is classified as one of the following:

Check warning on line 12 in standard/expressions.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/expressions.md#L12

MDC032::Line length 82 > maximum 81
- A value. Every value has an associated type.
- A variable. Unless otherwise specified, a variable is explicitly typed and has an associated type, namely the declared type of the variable. An implicitly typed variable has no associated type.
- A null literal. An expression with this classification can be implicitly converted to a reference type or nullable value type.
Expand Down Expand Up @@ -2526,6 +2526,11 @@
object_creation_expression
: 'new' type '(' argument_list? ')' object_or_collection_initializer?
| 'new' type object_or_collection_initializer
| target_typed_new
;

target_typed_new
: 'new' '(' argument_list? ')' object_or_collection_initializer?
;

object_or_collection_initializer
Expand All @@ -2536,6 +2541,10 @@

The *type* of an *object_creation_expression* shall be a *class_type*, a *value_type*, or a *type_parameter*. The *type* cannot be a *tuple_type* or an abstract or static *class_type*.

If `type` can be inferred from usage, it can be omitted, as allowed by *target_typed_new*. It is a compile-time error to omit `type` if the type cannot be inferred. A *target_typed_new* expression has no type. However, there is an implicit object-creation conversion (§imp-obj-creation-conv) from a *target_typed_new* expression to every type. It is a compile-time error if a *target_typed_new* is used as an operand of a unary or binary operator, or if it is used where it is not subject to an object-creation 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.

"If type can be inferred from usage" is too vague here.

For example, if I have:

void M(int x) { ... }
void M(Guid g) { ... }

... then can I write M(new(new byte[16])) as Guid has a constructor that accepts a byte array, but int doesn't?

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 strongly suspect that clarifying this will be the biggest change required for this feature. I don't know whether we'll need to consider everywhere that target_typed_new can exist...)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This one will be tough. Your example generates CS0121: The call is ambiguous between M(Guid) and M(int). That's weird, because int y = new(new byte[16])) correctly doesn't compile.

The example in the speclet shows a method with several overloads, XmlReader.Create. But, in that case, all the overloads have the same type as the 2nd positional parameter, so it's obvious what to create.

Now, if you use this: M(g: new(new byte[16]));, it compiles (note the named parameter). If you change the definition of both M methods so that the parameter name is the same, it's ambiguous again.


If `type` is present, let `T` be that type; otherwise, let `T` be the implied type.

The optional *argument_list* ([§12.6.2](expressions.md#1262-argument-lists)) is permitted only if the *type* is a *class_type* or a *struct_type*.

An object creation expression can omit the constructor argument list and enclosing parentheses provided it includes an object initializer or collection initializer. Omitting the constructor argument list and enclosing parentheses is equivalent to specifying an empty argument list.
Expand All @@ -2544,7 +2553,7 @@

If any of the arguments in the optional *argument_list* has the compile-time type `dynamic` then the *object_creation_expression* is dynamically bound ([§12.3.3](expressions.md#1233-dynamic-binding)) and the following rules are applied at run-time using the run-time type of those arguments of the *argument_list* that have the compile-time type `dynamic`. However, the object creation undergoes a limited compile-time check as described in [§12.6.5](expressions.md#1265-compile-time-checking-of-dynamic-member-invocation).

The binding-time processing of an *object_creation_expression* of the form `new T(A)`, where `T` is a *class_type*, or a *value_type*, and `A` is an optional *argument_list*, consists of the following steps:
The binding-time processing of an *object_creation_expression* of the form `new T(A)`, where the specified or implied type `T` is a *class_type*, or a *value_type*, and `A` is an optional *argument_list*, consists of the following steps:

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.

A target-typed new expression isn't "of the form new T(A)... I think this can probably be fixed by saying something along the lines of "or a target_typed_new expression with an implied type T".

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.

(Existing potential problem) Should this include object_or_collection_initializer?? It's sort of described earlier, but it's not really clear. We could potentially make it clear by saying that processing an expression which contains an object or collection initializer is equivalent to processing an expression without it, and then executing the object/collection initializer. Although I suspect init-only properties might make that tricky.

If it's not intended to exclude that case, why use "of the form" at all?


- If `T` is a *value_type* and `A` is not present:
- The *object_creation_expression* is a default constructor invocation. The result of the *object_creation_expression* is a value of type `T`, namely the default value for `T` as defined in [§8.3.3](types.md#833-default-constructors).
Expand All @@ -2559,7 +2568,7 @@

Even if the *object_creation_expression* is dynamically bound, the compile-time type is still `T`.

The run-time processing of an *object_creation_expression* of the form new `T(A)`, where `T` is *class_type* or a *struct_type* and `A` is an optional *argument_list*, consists of the following steps:
The run-time processing of an *object_creation_expression* of the form `new T(A)`, where the specified or implied type `T` is *class_type* or a *struct_type* and `A` is an optional *argument_list*, consists of the following steps:

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.

Another example of the same kind of thing.


- If `T` is a *class_type*:
- A new instance of class `T` is allocated. If there is not enough memory available to allocate the new instance, a `System.OutOfMemoryException` is thrown and no further steps are executed.
Expand Down
2 changes: 1 addition & 1 deletion standard/statements.md
Original file line number Diff line number Diff line change
Expand Up @@ -1739,7 +1739,7 @@ throw_statement
;
```

A `throw` statement with an expression throws an exception produced by evaluating the expression. The expression shall be implicitly convertible to `System.Exception`, and the result of evaluating the expression is converted to `System.Exception` before being thrown. If the result of the conversion is `null`, a `System.NullReferenceException` is thrown instead.
A `throw` statement with an expression throws an exception produced by evaluating the expression. The expression shall be implicitly convertible to `System.Exception`, and the result of evaluating the expression is converted to `System.Exception` before being thrown. If *expression* is a *target_typed_new* expression ([§12.8.17.2](expressions.md#128172-object-creation-expressions)), the target type is `System.Exception`. If the result of the conversion is `null`, a `System.NullReferenceException` is thrown instead.

A `throw` statement with no expression can be used only in a `catch` block, in which case, that statement re-throws the exception that is currently being handled by that `catch` block.

Expand Down
Loading