- "Did I spell legite correctly? My Memory isn't that great" "No, it's legit. Trailing e would make it like vegemite."
We started today by looking over a new proposal aimed at addressing a few pain points with Span
and ReadOnlySpan
that the language and library authors
have encountered since their introduction. These are areas that arrays work well in, but Span
and ReadOnlySpan
do not. To that end, we reviewed a
proposal for treating these types more specially in the language, much as we do for array types. We had a few thoughts on specific parts of the proposal:
- Even though
ReadOnlySpan<T>
exposes theT
byref
, it's always areadonly ref
, so we're fine to treat it as if it's covariant. If theT
was just byref
, it wouldn't be safe. - We're fine with
is
not working covariantly. This is the same thing asint
tolong
conversions: C# can do it, but the runtime doesn't know about the conversion in type checking. - We thought about whether this should extend to
Memory<T>
, but are wary of it.Memory<T>
does not have an implicit conversion toSpan<T>
/ReadOnlySpan<T>
because, depending on the backing storage, it can have a cost to convert, and we'd be worried about suddenly creating such conversions in the language.- At the same time, though, we are also sympathetic to the concern that, if a code path needs to be
async
ified and converted toMemory<T>
, that may necessitate more changes to allow what works forSpan<T>
to work in theasync
world.
- At the same time, though, we are also sympathetic to the concern that, if a code path needs to be
- We may need to keep special cases for betterness to keep
ReadOnlySpan<T>
better thanSpan<T>
; in the psuedo type hierarchy,Span<T>
is better thanReadOnlySpan<T>
, because it is more specific. However, this is not what we want overload resolution to choose, sinceSpan<T>
offers worse performance in most cases.
Overall, we like the direction of this proposal, and want to proceed with it. We'll answer open questions as implementation progresses.
Proposal is accepted.
Next, we looked at one of the collection expression topics we want to handle in C# 13, inline collection expression usage. These are scenarios where a collection
expression is immediately used and never observed outside an expression, usually to handle some kind of conditional addition to a collection, or to enumerate
in a foreach
. The main question here is whether we should rely purely on natural typing for these scenarios, or whether target element typing should flow in
somehow. For example:
// If `byte` doesn't flow into the conditional as an element type, the natural element type will be `int`, and the conversion will fail
byte[] x = [1, .. b ? [2] : []];
// If `bool?` doesn't flow into the iteration expression, there will be a compile error because no natural type can be found
foreach (bool? b in [true, false, null]) {}
We do have some disagreements on how exactly that information would flow into the expression to give it a final type: do we have to have some stopgap solution until we have a natural type concept, or can we just integrate with that? We're generally in agreement that these examples should be able to compile, meaning that we are generally in favor of flowing in an element type in some fashion. With this direction, we think the working group can take the lead on integrating with natural typing work and then propose the final approach to LDM (or propose that it doesn't integrate with specific reasoning for why it shouldn't).
We are in favor of target element typing flowing into collection expressions.