Skip to content

Latest commit

 

History

History
103 lines (74 loc) · 6.23 KB

LDM-2023-05-03.md

File metadata and controls

103 lines (74 loc) · 6.23 KB

C# Language Design Meeting for May 3rd, 2023

Agenda

Quote of the Day

  • "It's our best chance of having a stem cell"

Discussion

Inline Arrays

#1314
#7130

Continuing to follow up on open questions, we turned our attention to validating InlineArrayAttribute applications and whether nested object initializers can use indexers on inline arrays. For the former, we're unanimously in favor of the compiler validating that the attribute was applied correctly. The latter proved to be a more interesting conversation; we brought up that arrays are supported, but this actually appears to be a spec violation of the C# compiler, as the syntax is supposed to require an indexer member to be defined on the type being initialized while arrays do not define any such member. We also don't think there's any real demand for this to be natively supported, and by leaving it out users can opt into the feature by defining their own indexer on their inline array types. This allows us to have our cake and eat it too: no implementation complexity for us, and users can get the syntax they choose if they want it.

Conclusion

We will validate InlineArrayAttribute applications. We will not natively support inline arrays for object initializer index initialization, but we won't block it if the user defines their own indexer either.

Primary constructors

#2691

We considered a couple of open questions in primary ctors.

Attributes on captured parameters

https://github.com/dotnet/csharplang/blob/fe9915c0708cf95c308cce33983373641fc1b60d/proposals/primary-constructors.md#field-targeting-attributes-for-captured-primary-constructor-parameters

We're concerned about allowing attributes on captured parameters. From a language perspective, these are not fields, and don't have to be captured in fields. This would not be the only thing that a user might want to put on their captures; for example, there has been significant feedback that users would like their captures to be readonly. This doesn't seem more important than that scenario, so why would this work while that does not? It seems like, if we ever get syntax for specifying more about how the parameter is captured, it would be appropriate to have this feature at that point, but until then we would like to hold off.

Conclusion

Not allowed.

Warning for shadowing base members

#7109 (reply in thread)

One piece of feedback that we've seen is that users are concerned about shadowing members from base types accidentally. While this is concerning, we're also concerned that a broad warning might impact a common scenario where the parameter is passed to the base to initialize the shadowing member. We need to think more about this conflict, so we'll do so and come back to the problem at a later meeting.

Conclusion

No conclusion today.

Collection literal natural type

#5354
https://github.com/dotnet/csharplang/blob/c8c1615fcad4ca016a97b7260ad497aad53ebc78/meetings/working-groups/collection-literals/CL-2023-04-28.md#should-a-collection-literal-have-a-natural-type-if-so-what-type

Finally today, we considered whether collection literals should have a natural type. There are a couple of slightly different versions of this scenario: var, and IEnumerable<>, but var is what we spent most of the time discussing. In many ways, a natural type for a collection is going to be surprising, no matter what we choose. Some users will expect such collections to behave like other C# literals: immutable and cacheable. Another segment might expect the literal to be typed as an array: not immutable, but not growable either. A third would expect such literals to be a type that can be added to later, such as List<>. No matter what we choose, if we choose a natural type, two of the segments are going to be surprised by the decision.

So what if we didn't have a natural type at all? Today, users always need to think about the type of a collection when it is created. Either it needs to be assigned to a local or parameter that has a type, or it's being created by some factory method or constructor that has to be typed. One of the goals of the proposal to simplify this, and that requires having a natural type. But it does feel odd that, for a proposal that goes so far to be optimal when we know the target type, it cannot be optimal in the natural type case. For the cohort of users that want these to be immutable, any mutability in the natural type means that the literals cannot be cached, resulting in lots of extra allocations. For those that expect an array, using List<> or some other similar type means that extra overhead is incurred, and trivial cases like empty literals cannot be shared. For users who expect List<>, either of the other two means that they will have to specify the collection type at creation, making it no longer a simple scenario. Unfortunately, not having a target type at the start and then adding one later is potentially a breaking change. We did it for lambdas, but it caused significant pain for implementation and has a number of caveats, so if we can avoid the same gymnastics that would be helpful.

We also thought a bit about a middle ground, where a collection literal only has a natural type when it is observably stored in a location. For example, when iterated over in a foreach, a collection literal could be emitted however is most efficient for the compiler. This does then introduce another risk of deoptimizing by extracting variables. This can already happen with interpolated string handlers, but that is fairly rare. This might be similarly rare, but more such cases always need to be approached with caution.

We have no conclusions here this week. We'll come back and think about it more in a future LDM.