- "I think the entire language is biased to developers general nature to be introverted. Sure, we can have variables as int j and int p, but to be really inclusive we need ent j and ent p."
- "'Enthusiastic Markdown File' is the name of my new punk band"
- "Just to clarify, you were talking about heinous rule number 3?"
- "The language of 1000 keywords"
- "I don't know why I'm passing methane around" "You're passing gas"
We got some feedback on our proposal for collection expressions that we wanted to consider in relation to list patterns, before they ship in C# 11 and we can't take back our decisions.
Specifically, there is concern that using ..
for slicing in list patterns is setting us up for ambiguities in the future with collection literals, where we want ..
to mean add all
elements of a sublist to the list being created. This would make the syntax potentially ambiguous when constructing a list of ranges, as var x = [1.., .. b, 3..4]
could mean add all
the elements of b
to x
, or it could mean add the range .. b
to x
.
Our original motivation for using ..
as the slice pattern was for a different form of consistency: ranges are used to slice collections, so the ..
pattern implicitly slices, where
the access form would be var x = array[1..3];
. So no matter what we do here, there will be some form of inconsistency: either slicing has the inconsistency, or we'll need to parenthesize
ranges in collection literals to make a collection of ranges. We have a few different proposals on what do here:
- Do nothing.
- Use a different syntax. We looked through a few suggestions and other language's spread/splat operators:
...
- used by JS, TS, and Dart, among others.*
- used by Ruby and Python#
- Suggested on csharplang
- Create a "spread/splat" operator context, as a separable feature from list patterns.
We explored the other proposed syntaxes, but nothing immediately stood out as obvious and the right choice. We like the existing consistency of the ..
operator between slicing expressions
and slicing patterns, and none of the other syntaxes would keep that. We also did a bit of exploration on proposal 3, and after some discussion we think that there's a potential feature
there. We might be able to say that ..
on Index
and int
expressions creates a Range
, and for any other type it performs a spread/splat operation, when in a spread/splat context. We
didn't get too far into details around what constitutes such a context, but far enough that we think our future selves will be able to define such contexts.
We will explore option 3 when we get more in-depth on collection literals, and will keep ..
as the syntax for slice patterns.
We looked at open questions in main
attributes, starting with where to allow main
and what that specifier should apply to. Every option for allowing main
in a different file has a set
of downsides associated with it:
- If we allow
main
in other files to target any entry point, that means that we introduce a new project file switch that affects the language, as the project file can set what the entry point is. This means that the attributes applied to a specificMain
will change based on the project file, which we immediately dislike. - If we allow
main
in other files to only target top-level statements, then top-level statements suddenly become not just a stylistic choice, but one that affects what other features of the language can be used. This will make an inconsistent experience for users of generators that want to use the feature.
We further examined the motivating use case for this feature, STAThread
in WinForms. After some review, we're not convinced of this as a motivation. The Main
method in a WinForms
application is basically never touched: in VB, it's even hidden from the user. It seems to us that a source generator could simply generate the entire Main
method for the scenario, rather
than just adding STAThread
as an attribute to it. While we think that a main
specifier in the same file might find some use in the future, we don't think we currently have a scenario
that supports moving it forward.
Allowing main
in other files is removed from the proposal, and we will move the proposal to the backlog for consideraton when we have a better motivating scenario for it.
This proposal introduces a potential breaking change that we need to consider: by bringing parameters into scope, we potentially cause a dotted expression to bind to the parameter, instead
of whatever it binds to now. This, in turn, could cause existing code to no longer compile. We think it's a good change overall though: we generally wish we had designed nameof
this way
in the beginning, and we think the likelihood of the break is low. The most likely thing for a parameter to collide with is a field of the same name, and this will most often be of the same
type, so existing code will continue to compile, even if it refers to a member through a different path now. We do want to get it out in preview soon, so that we can assess the extent of people
broken by this change, but we expect it to be very low.
We'll accept the breaking change, and get it into preview soon to ensure that we can understand how many users it might affect.