- "I think I have the record for how many times my brain stumbled on this today."
Champion issues: #8374, #7700
Spec change: #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.
Proposed rules are adopted.
Champion issue: #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.
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.
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 throughReadOnlySpan
. - Expose an
Assert.Equals<T>(ReadOnlySpan<T> expected, T[] actual)
, which will be preferred forAssert.Equals([1, 2], somethingThatIsAnArray)
.
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.
We accept all of these breaks.