# C# Language Design Meeting for January 8th, 2024

## Agenda

- [Collection expressions](#collection-expressions)
    - [Iteration type of `CollectionBuilderAttribute` collections](#iteration-type-of-collectionbuilderattribute-collections)
    - [Iteration type in conversions](#iteration-type-in-conversions)

## Quote of the Day

- "Can we do another one in 15 minutes?" "I think it'll take another whole meeting"

## Discussion

### Collection expressions

#### Iteration type of `CollectionBuilderAttribute` collections

https://github.com/dotnet/csharplang/issues/5354  
https://github.com/dotnet/csharplang/blob/1f55d3c05d549edc817589502bfee90db887d56e/proposals/csharp-12.0/collection-expressions.md#specification-of-a-constructible-collection-type-utilizing-a-create-method-is-sensitive-to-the-context-at-which-conversion-is-classified

First up today, we looked at a change to how collection expressions determine the iteration type of a collection expression, motivated by our work on `params` improvements.
Our specification for `CollectionBuilder` types does not require that they define their own iteration types, but can instead pick them up through extension methods; this means
that it is possible that a `params` parameter is only valid as `params` in some contexts, not all. This is potentially undesirable for users, and it means that it is very hard
to give correct errors for `params` parameters. The current behavior was intentional, as it is mirror to `foreach`, but we are sympathetic to the idea that, if a type can be
created by a collection expression, it should also be generally foreachable. Extension `GetEnumerator` can be used to add `foreach`ability to a type, but we are fine with saying
that such types cannot be constructed with a collection expression, and that types that use `CollectionBuilder` should actually define their own iteration types. We will take this
for a C# 12 update (in the 8.0.2xx or 8.0.3xx branch of .NET 8), not hold it until C# 13.

We also thought about whether to require that the `Create` method specified by the `CollectionBuilder` attribute is public, for symmetry with `GetEnumerator`. We're not convinced
of this one: it seems like perfectly reasonable public API policy to expose a type that is publicly foreachable, but not publicly buildable. It does mean that users can put `params`
on a parameter in a method that is more visible than the `Create` method for creating the parameter, but that seems squarely a mistake of API design, and not something that C#
should prevent.

##### Conclusion

We will require that types with a `CollectionBuilder` have a public iteration type. This means either implementing one of the `IEnumerable` interfaces, or providing a `GetEnumerator`
method. We will not require that their `Create` methods are any particular visibility, as today.

#### Iteration type in conversions

https://github.com/dotnet/csharplang/issues/5354  
https://github.com/dotnet/csharplang/blob/1f55d3c05d549edc817589502bfee90db887d56e/proposals/csharp-12.0/collection-expressions.md#the-notion-of-iteration-type-is-not-applied-consistently-throughout-conversions

The wording of how collection expression conversions are determined can lead to some confusion in particularly weird scenarios, when a type that implements `IEnumerable<T>` does so
privately and its iteration type is actually completely different. We will therefore change the wording to reflect the iteration type directly, rather than special casing the various
`IEnumerable` interfaces. This has the benefit of simplifying the specification, and we expect that it will affect no real user code except the compiler test base.

##### Conclusion

Change is accepted. We will reword the conversion existence part of the specification to be based on iteration type directly.
