From c925991a4ba2aff8885bc103ce1869872c0c861e Mon Sep 17 00:00:00 2001 From: Charles Stoner <10732005+cston@users.noreply.github.com> Date: Fri, 29 Mar 2024 11:09:57 -0700 Subject: [PATCH] Collection expressions: require Add method callable with a single argument for class and struct types that do not use [CollectionBuilder] (#8022) --- proposals/csharp-12.0/collection-expressions.md | 10 +++++++--- proposals/params-collections.md | 13 ++++++++----- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/proposals/csharp-12.0/collection-expressions.md b/proposals/csharp-12.0/collection-expressions.md index 98b36cf5..929771c3 100644 --- a/proposals/csharp-12.0/collection-expressions.md +++ b/proposals/csharp-12.0/collection-expressions.md @@ -110,9 +110,13 @@ An implicit *collection expression conversion* exists from a collection expressi in which cases the *element type* is `T` * A *type* with an appropriate *[create method](#create-methods)* and a corresponding *element type* resulting from that determination * A *struct* or *class type* that implements `System.Collections.IEnumerable` where: - * The *type* has an *[applicable](https://github.com/dotnet/csharpstandard/blob/standard-v6/standard/expressions.md#11642-applicable-function-member)* constructor that can be invoked with no arguments, and the constructor is accessible at the location of the collection expression, and - * If the collection expression has any elements, the *type* has an *[applicable](https://github.com/dotnet/csharpstandard/blob/standard-v6/standard/expressions.md#11642-applicable-function-member)* instance or extension method `Add` that can be invoked with a single argument of the [*iteration type*](https://github.com/dotnet/csharpstandard/blob/standard-v6/standard/statements.md#1295-the-foreach-statement), and the method is accessible at the location of the collection expression, - in which case the *element type* is the *iteration type* of the *type*. + * The *type* has an *[applicable](https://github.com/dotnet/csharpstandard/blob/standard-v6/standard/expressions.md#11642-applicable-function-member)* constructor that can be invoked with no arguments, and the constructor is accessible at the location of the collection expression. + * If the collection expression has any elements, the *type* has an instance or extension method `Add` where: + * The method can be invoked with a single value argument. + * If the method is generic, the type arguments can be inferred from the collection and argument. + * The method is accessible at the location of the collection expression. + + In which case the *element type* is the [*iteration type*](https://github.com/dotnet/csharpstandard/blob/standard-v6/standard/statements.md#1295-the-foreach-statement) of the *type*. * An *interface type*: * `System.Collections.Generic.IEnumerable` * `System.Collections.Generic.IReadOnlyCollection` diff --git a/proposals/params-collections.md b/proposals/params-collections.md index e19d76bb..af84c56d 100644 --- a/proposals/params-collections.md +++ b/proposals/params-collections.md @@ -55,11 +55,13 @@ The *type* of a parameter collection shall be one of the following valid target - A *type* with an appropriate *[create method](https://github.com/dotnet/csharplang/blob/main/proposals/csharp-12.0/collection-expressions.md#create-methods)*, which is at least as accessible as the declaring member, and with a corresponding *element type* resulting from that determination - A *struct* or *class type* that implements `System.Collections.IEnumerable` where: - - The *type* has a constructor that can be invoked with no arguments, and the constructor is at least as accessible as the declaring member, and - - The *type* has an instance (not an extension) method `Add` that can be invoked with a single argument of - the [*iteration type*](https://github.com/dotnet/csharpstandard/blob/draft-v9/standard/statements.md#1395-the-foreach-statement), - and the method is at least as accessible as the declaring member, - in which case the *element type* is the *iteration type* + - The *type* has a constructor that can be invoked with no arguments, and the constructor is at least as accessible as the declaring member. + - The *type* has an instance (not an extension) method `Add` where: + - The method can be invoked with a single value argument. + - If the method is generic, the type arguments can be inferred from the argument. + - The method is at least as accessible as the declaring member. + + In which case the *element type* is the [*iteration type*](https://github.com/dotnet/csharpstandard/blob/draft-v9/standard/statements.md#1395-the-foreach-statement) of the *type*. - An *interface type* - `System.Collections.Generic.IEnumerable`, - `System.Collections.Generic.IReadOnlyCollection`, @@ -94,6 +96,7 @@ A parameter collection permits arguments to be specified in one of two ways in a [Collection expressions](https://github.com/dotnet/csharplang/blob/main/proposals/csharp-12.0/collection-expressions.md) as though the arguments were used as expression elements in a collection expression in the same order, and uses the newly created collection instance as the actual argument. + When constructing the collection instance, the original *unconverted* arguments are used. Except for allowing a variable number of arguments in an invocation, a parameter collection is precisely equivalent to a value parameter of the same type.