# C# Language Design Meeting for September 11th, 2024

## Agenda

- [Better conversion from collection expression and `params` collections](#better-conversion-from-collection-expression-and-params-collections)
- [First-class span types](#first-class-span-types)
    - [`Reverse`](#reverse)
    - [New ambiguities](#new-ambiguities)
    - [Covariant arrays](#covariant-arrays)

## Quote of the Day

- "I think I have the record for how many times my brain stumbled on this today."

## Discussion

### Better conversion from collection expression and `params` collections

Champion issues: https://github.com/dotnet/csharplang/issues/8374, https://github.com/dotnet/csharplang/issues/7700  
Spec change: https://github.com/dotnet/csharplang/pull/8393

We started today by looking at an explicit consequence of our better conversion from collection expression changes and ensuring that we were ok with it. In our view of element type being the most important thing,
this is a natural consequence and we're ok with it. We're also ok with how it aligns more with how `params` arrays has always worked; for example, `params int[]` has always been ambiguous with `params int?[]`
when called with 0 elements, and this lines up with that behavior. We also looked at the proposed change to `params` collections. This is also in the name of consistency; we want to make the rules for the new
feature consistent with the new rules for the old feature. All together, these changes bring everything together with near-complete consistency, which we strongly like.

#### Conclusion

Proposed rules are adopted.

### First-class span types

Champion issue: https://github.com/dotnet/csharplang/issues/7905

Finally today, we went over some possible breaking changes that will be caused by first-class spans. We knew going into this that there would be breaking changes, so that we have them isn't a surprise, but in
the name of due diligence we want to go through them and make sure that we're comfortable with them.

#### `Reverse`

https://github.com/dotnet/csharplang/blob/38c28b88c3e9ea9fb076b39c8d204f2b189b6796/proposals/first-class-span-types.md#calling-reverse-on-an-array

The word `Reverse` is unfortunately too useful; it's both in `LINQ`, as "Please give me a stream that is the reverse of my input stream", as well as in `MemoryExtensions` as "Please in-place reverse this `Span`".
Currently, only the former thing is applicable. After this feature, both will be applicable, and the `Span` version will win. There is a workaround for the BCL (add `Reverse(array)` to `Enumerable`), which we
expect them to do to address this break. Ultimately, we're ok with this break; it's the way that we'd have wanted it to be in the first place, and the overall likelihood that there are identically named methods
with different semantics is pretty low, as that usually breaks the guidance in the API design guidelines: https://learn.microsoft.com/en-us/dotnet/standard/design-guidelines/member-overloading.

#### New ambiguities

https://github.com/dotnet/csharplang/blob/38c28b88c3e9ea9fb076b39c8d204f2b189b6796/proposals/first-class-span-types.md#ambiguities

For this case (which arises in assert methods like `Assert.Equals` in xUnit, NUnit, and MSTest), it's a bit unfortunate, but there are also several options available to API authors. In many ways, this is simply
a historical design artifact of the lack of `ReadOnlySpan` and the lack of this conversion in the first place: if these APIs were to be rewritten just with this feature, then they could just have exposed `ReadOnlySpan`
overloads and been done with it. We see two possible avenues for these APIs:

* Apply `OverloadResolutionPriority(-1)` to their array-based overloads, so everything goes through `ReadOnlySpan`.
* Expose an `Assert.Equals<T>(ReadOnlySpan<T> expected, T[] actual)`, which will be preferred for `Assert.Equals([1, 2], somethingThatIsAnArray)`.

#### Covariant arrays

https://github.com/dotnet/csharplang/blob/38c28b88c3e9ea9fb076b39c8d204f2b189b6796/proposals/first-class-span-types.md#covariant-arrays

Covariant arrays, our favorite feature, strikes again. However, we're unsure that this is a real case that users will hit. We'll certainly document it, but this particular code example came from our unit tests,
which aren't always reflective of real things users will write. Given this, we're also ok with this break.

#### Conclusion

We accept all of these breaks.
