From 37e3a9c294b8fd7766dcf976c13cb78ad4adb5cb Mon Sep 17 00:00:00 2001 From: Bill Wagner Date: Fri, 23 Oct 2020 16:00:13 -0400 Subject: [PATCH 1/8] specification for initializers --- standard/expressions.md | 56 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 51 insertions(+), 5 deletions(-) diff --git a/standard/expressions.md b/standard/expressions.md index 24b2b9417..0dfa28103 100644 --- a/standard/expressions.md +++ b/standard/expressions.md @@ -1784,7 +1784,7 @@ The run-time processing of an *object_creation_expression* of the form new `T(A) #### 12.7.14.3 Object initializers -An ***object initializer*** specifies values for zero or more fields or properties of an object. +An ***object initializer*** specifies values for zero or more fields, properties, or indexed elements of an object. ```ANTLR object_initializer @@ -1797,7 +1797,12 @@ member_initializer_list ; member_initializer - : identifier '=' initializer_value + : initializer_target '=' initializer_value + ; + +initializer_target + : identifier + | '[' argument_list ']' ; initializer_value @@ -1806,13 +1811,21 @@ initializer_value ; ``` -An object initializer consists of a sequence of member initializers, enclosed by `{` and `}` tokens and separated by commas. Each member initializer shall name an accessible field or property of the object being initialized, followed by an equals sign and an expression or an object initializer or collection initializer. It is an error for an object initializer to include more than one member initializer for the same field or property. It is not possible for the object initializer to refer to the newly created object it is initializing. +An object initializer consists of a sequence of member initializers, enclosed by `{` and `}` tokens and separated by commas. Each *member_initializer* shall designate a target for the initialization. An *identifier* shall name an accessible field or property of the object being initialized, whereas an *argument_list* enclosed in square brackets shall specify arguments for an accessible indexer on the object being initialized. It is an error for an object initializer to include more than one member initializer for the same field or property. -A member initializer that specifies an expression after the equals sign is processed in the same way as an assignment ([§12.18.2](expressions.md#12182-simple-assignment)) to the field or property. +Each *initializer_target* is followed by an equals sign and either an expression, an object initializer or a collection initializer. It is not possible for expressions within the object initializer to refer to the newly created object it is initializing. + +A member initializer that specifies an expression after the equals sign is processed in the same way as an assignment ([§12.18.2](expressions.md#12182-simple-assignment)) to the target. A member initializer that specifies an object initializer after the equals sign is a ***nested object initializer***, i.e., an initialization of an embedded object. Instead of assigning a new value to the field or property, the assignments in the nested object initializer are treated as assignments to members of the field or property. Nested object initializers cannot be applied to properties with a value type, or to read-only fields with a value type. +<<<<<<< HEAD A member initializer that specifies a collection initializer after the equals sign is an initialization of an embedded collection. Instead of assigning a new collection to the field or property, the elements given in the initializer are added to the collection referenced by the field or property. The field or property shall be of a collection type that satisfies the requirements specified in [§12.7.14.4](expressions.md#127144-collection-initializers). +======= +A member initializer that specifies a collection initializer after the equals sign is an initialization of an embedded collection. Instead of assigning a new collection to the target field, property or indexer, the elements given in the initializer are added to the collection referenced by the target. The target shall be of a collection type that satisfies the requirements specified in [§12.7.11.4](expressions.md#127114-collection-initializers). + +The arguments to an index initializer shall always be evaluated exactly once. Thus, even if the arguments end up never getting used (e.g., because of an empty nested initializer), they are evaluated for their side effects. +>>>>>>> 8f91536 (specification for initializers) > *Example*: The following class represents a point with two coordinates: > ```csharp @@ -1893,7 +1906,40 @@ A member initializer that specifies a collection initializer after the equals si > ``` > *end example* +<<<<<<< HEAD #### 12.7.14.4 Collection initializers +======= +> *Example*: Given an appropriate definition of `C`, the following example: +> ```csharp +> var c = new C { +> x = true, +> y = { a = "Hello" }, +> z = { 1, 2, 3 }, +> ["x"] = 5, +> [0,0] = { "a", "b" }, +> [1,2] = {} +> }; +> ``` +> is equivalent to this series of assignments: +> ```csharp +> C __c = new C(); +> __c.x = true; +> __c.y.a = "Hello"; +> __c.z.Add(1); +> __c.z.Add(2); +> __c.z.Add(3); +> string __i1 = "x"; +> __c[__i1] = 5; +> int __i2 = 0, __i3 = 0; +> __c[__i2,__i3].Add("a"); +> __c[__i2,__i3].Add("b"); +> int __i4 = 1, __i5 = 2; +> var c = __c; +> ``` +> where `__c`, etc., are generated variables that are invisible and inaccessible to the source code. Note that the arguments for `[0,0]` are evaluated only once, and the arguments for `[1,2]` are evaluated once even though they are never used. *end example* + +#### 12.7.11.4 Collection initializers +>>>>>>> 8f91536 (specification for initializers) A collection initializer specifies the elements of a collection. @@ -1927,7 +1973,7 @@ A collection initializer consists of a sequence of element initializers, enclose > ``` > *end example* -The collection object to which a collection initializer is applied shall be of a type that implements `System.Collections.IEnumerable` or a compile-time error occurs. For each specified element in order, the collection initializer invokes an `Add` method on the target object with the expression list of the element initializer as argument list, applying normal overload resolution for each invocation. Thus, the collection object shall contain an applicable `Add` method for each element initializer. +The collection object to which a collection initializer is applied shall be of a type that implements `System.Collections.IEnumerable` or a compile-time error occurs. For each specified element in order, the collection initializer invokes an `Add` method on the target object with the expression list of the element initializer as argument list, applying normal member lookup and overload resolution for each invocation. Thus, the collection object shall contain an applicable instance or extension method with the name `Add` for each element initializer. > *Example*:The following class represents a contact with a name and a list of phone numbers: > ```csharp From f2484b9a477a88f1db085b8b0188d7c310d9db15 Mon Sep 17 00:00:00 2001 From: Bill Wagner Date: Mon, 30 Nov 2020 17:10:37 -0500 Subject: [PATCH 2/8] revert a mistaken edit An edit for await in catch and finally clauses (#3) snuck into this PR --- standard/expressions.md | 1 + 1 file changed, 1 insertion(+) diff --git a/standard/expressions.md b/standard/expressions.md index 0dfa28103..3dd723609 100644 --- a/standard/expressions.md +++ b/standard/expressions.md @@ -2755,6 +2755,7 @@ await_expression An *await_expression* is only allowed in the body of an async function ([§15.15](classes.md#1515-async-functions)). Within the nearest enclosing async function, an *await_expression* shall not occur in these places: - Inside a nested (non-async) anonymous function +- In a `catch` or `finally` block of a *try_statement* - Inside the block of a *lock_statement* - In an anonymous function conversion to an expression tree type ([§11.7.3](conversions.md#1173-evaluation-of-anonymous-function-conversions-to-expression-tree-types)) - In an unsafe context From 3dc0a92b0011c1da8565ae652e6fcdccc2b4dc34 Mon Sep 17 00:00:00 2001 From: Bill Wagner Date: Wed, 17 Nov 2021 16:18:38 -0500 Subject: [PATCH 3/8] fix merge mistakes. --- standard/expressions.md | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/standard/expressions.md b/standard/expressions.md index 3dd723609..6a8c71ae6 100644 --- a/standard/expressions.md +++ b/standard/expressions.md @@ -1819,13 +1819,9 @@ A member initializer that specifies an expression after the equals sign is proce A member initializer that specifies an object initializer after the equals sign is a ***nested object initializer***, i.e., an initialization of an embedded object. Instead of assigning a new value to the field or property, the assignments in the nested object initializer are treated as assignments to members of the field or property. Nested object initializers cannot be applied to properties with a value type, or to read-only fields with a value type. -<<<<<<< HEAD -A member initializer that specifies a collection initializer after the equals sign is an initialization of an embedded collection. Instead of assigning a new collection to the field or property, the elements given in the initializer are added to the collection referenced by the field or property. The field or property shall be of a collection type that satisfies the requirements specified in [§12.7.14.4](expressions.md#127144-collection-initializers). -======= -A member initializer that specifies a collection initializer after the equals sign is an initialization of an embedded collection. Instead of assigning a new collection to the target field, property or indexer, the elements given in the initializer are added to the collection referenced by the target. The target shall be of a collection type that satisfies the requirements specified in [§12.7.11.4](expressions.md#127114-collection-initializers). +A member initializer that specifies a collection initializer after the equals sign is an initialization of an embedded collection. Instead of assigning a new collection to the target field, property or indexer, the elements given in the initializer are added to the collection referenced by the target. The target shall be of a collection type that satisfies the requirements specified in [§12.7.14.4](expressions.md#127144-collection-initializers). The arguments to an index initializer shall always be evaluated exactly once. Thus, even if the arguments end up never getting used (e.g., because of an empty nested initializer), they are evaluated for their side effects. ->>>>>>> 8f91536 (specification for initializers) > *Example*: The following class represents a point with two coordinates: > ```csharp From 20edf79e95da4877e42d6f88cd909262572dc1b6 Mon Sep 17 00:00:00 2001 From: Bill Wagner Date: Wed, 17 Nov 2021 16:25:46 -0500 Subject: [PATCH 4/8] one more merge mistake. --- standard/expressions.md | 33 --------------------------------- 1 file changed, 33 deletions(-) diff --git a/standard/expressions.md b/standard/expressions.md index 6a8c71ae6..dc4fff037 100644 --- a/standard/expressions.md +++ b/standard/expressions.md @@ -1902,40 +1902,7 @@ The arguments to an index initializer shall always be evaluated exactly once. Th > ``` > *end example* -<<<<<<< HEAD #### 12.7.14.4 Collection initializers -======= -> *Example*: Given an appropriate definition of `C`, the following example: -> ```csharp -> var c = new C { -> x = true, -> y = { a = "Hello" }, -> z = { 1, 2, 3 }, -> ["x"] = 5, -> [0,0] = { "a", "b" }, -> [1,2] = {} -> }; -> ``` -> is equivalent to this series of assignments: -> ```csharp -> C __c = new C(); -> __c.x = true; -> __c.y.a = "Hello"; -> __c.z.Add(1); -> __c.z.Add(2); -> __c.z.Add(3); -> string __i1 = "x"; -> __c[__i1] = 5; -> int __i2 = 0, __i3 = 0; -> __c[__i2,__i3].Add("a"); -> __c[__i2,__i3].Add("b"); -> int __i4 = 1, __i5 = 2; -> var c = __c; -> ``` -> where `__c`, etc., are generated variables that are invisible and inaccessible to the source code. Note that the arguments for `[0,0]` are evaluated only once, and the arguments for `[1,2]` are evaluated once even though they are never used. *end example* - -#### 12.7.11.4 Collection initializers ->>>>>>> 8f91536 (specification for initializers) A collection initializer specifies the elements of a collection. From 1a2d744fa938cac888a67295b7dc40d2f558849f Mon Sep 17 00:00:00 2001 From: Jon Skeet Date: Wed, 15 Dec 2021 20:12:07 +0000 Subject: [PATCH 5/8] Avoid "index initializer" as a non-defined term --- standard/expressions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/standard/expressions.md b/standard/expressions.md index dc4fff037..53ad5ec43 100644 --- a/standard/expressions.md +++ b/standard/expressions.md @@ -1821,7 +1821,7 @@ A member initializer that specifies an object initializer after the equals sign A member initializer that specifies a collection initializer after the equals sign is an initialization of an embedded collection. Instead of assigning a new collection to the target field, property or indexer, the elements given in the initializer are added to the collection referenced by the target. The target shall be of a collection type that satisfies the requirements specified in [§12.7.14.4](expressions.md#127144-collection-initializers). -The arguments to an index initializer shall always be evaluated exactly once. Thus, even if the arguments end up never getting used (e.g., because of an empty nested initializer), they are evaluated for their side effects. +When an initializer target refers to an indexer, the arguments to the indexer shall always be evaluated exactly once. Thus, even if the arguments end up never getting used (e.g., because of an empty nested initializer), they are evaluated for their side effects. > *Example*: The following class represents a point with two coordinates: > ```csharp From b9960654e1cb6e0c777f6a69c561cbdd7a95bf8b Mon Sep 17 00:00:00 2001 From: Jon Skeet Date: Wed, 15 Dec 2021 20:16:05 +0000 Subject: [PATCH 6/8] Require Add to be a method, not a property. --- standard/expressions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/standard/expressions.md b/standard/expressions.md index 53ad5ec43..ad1af718f 100644 --- a/standard/expressions.md +++ b/standard/expressions.md @@ -1936,7 +1936,7 @@ A collection initializer consists of a sequence of element initializers, enclose > ``` > *end example* -The collection object to which a collection initializer is applied shall be of a type that implements `System.Collections.IEnumerable` or a compile-time error occurs. For each specified element in order, the collection initializer invokes an `Add` method on the target object with the expression list of the element initializer as argument list, applying normal member lookup and overload resolution for each invocation. Thus, the collection object shall contain an applicable instance or extension method with the name `Add` for each element initializer. +The collection object to which a collection initializer is applied shall be of a type that implements `System.Collections.IEnumerable` or a compile-time error occurs. For each specified element in order, normal member lookup is applied to find a member named `Add`. If the result of the member lookup is not a method group, a compile-time error occurs. Otherwise, overload resolution is applied with the expression list of the element initializer as the argument list, and the collection initializer invokes the resulting method. Thus, the collection object shall contain an applicable instance or extension method with the name `Add` for each element initializer. > *Example*:The following class represents a contact with a name and a list of phone numbers: > ```csharp From c1e9e44adf979f765812fbb9ea5eec437b1dfbbf Mon Sep 17 00:00:00 2001 From: Bill Wagner Date: Wed, 15 Dec 2021 15:18:02 -0500 Subject: [PATCH 7/8] Update standard/expressions.md --- standard/expressions.md | 1 - 1 file changed, 1 deletion(-) diff --git a/standard/expressions.md b/standard/expressions.md index ad1af718f..6bdc9282a 100644 --- a/standard/expressions.md +++ b/standard/expressions.md @@ -2718,7 +2718,6 @@ await_expression An *await_expression* is only allowed in the body of an async function ([§15.15](classes.md#1515-async-functions)). Within the nearest enclosing async function, an *await_expression* shall not occur in these places: - Inside a nested (non-async) anonymous function -- In a `catch` or `finally` block of a *try_statement* - Inside the block of a *lock_statement* - In an anonymous function conversion to an expression tree type ([§11.7.3](conversions.md#1173-evaluation-of-anonymous-function-conversions-to-expression-tree-types)) - In an unsafe context From eed6370d9b86d5e58e6d9fed0960b6314a72428b Mon Sep 17 00:00:00 2001 From: Bill Wagner Date: Wed, 15 Dec 2021 16:21:29 -0500 Subject: [PATCH 8/8] fix section reference. --- standard/expressions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/standard/expressions.md b/standard/expressions.md index 8a7f113b6..d8cde33cb 100644 --- a/standard/expressions.md +++ b/standard/expressions.md @@ -2019,7 +2019,7 @@ A member initializer that specifies an expression after the equals sign is proce A member initializer that specifies an object initializer after the equals sign is a ***nested object initializer***, i.e., an initialization of an embedded object. Instead of assigning a new value to the field or property, the assignments in the nested object initializer are treated as assignments to members of the field or property. Nested object initializers cannot be applied to properties with a value type, or to read-only fields with a value type. -A member initializer that specifies a collection initializer after the equals sign is an initialization of an embedded collection. Instead of assigning a new collection to the target field, property, or indexer, the elements given in the initializer are added to the collection referenced by the target. The target shall be of a collection type that satisfies the requirements specified in [§12.7.14.4](expressions.md#127144-collection-initializers). +A member initializer that specifies a collection initializer after the equals sign is an initialization of an embedded collection. Instead of assigning a new collection to the target field, property, or indexer, the elements given in the initializer are added to the collection referenced by the target. The target shall be of a collection type that satisfies the requirements specified in [§12.7.15.4](expressions.md#127154-collection-initializers). When an initializer target refers to an indexer, the arguments to the indexer shall always be evaluated exactly once. Thus, even if the arguments end up never getting used (e.g., because of an empty nested initializer), they are evaluated for their side effects.