Replies: 9 comments
-
If primary constructors are to be a general purpose feature outside of records shouldn't those semantics be worked out first? Or does this mean that enough is known about how primary constructors should work alongside records that you can start the design around that? My concern is that records would ship first with primary constructors and that would lock their implementation before the semantics can be worked out that would enable them to be a more general purpose feature.
Is a builder approach not under consideration? A builder could validate that all of the required properties have been set and throw an exception otherwise, which should handle the lack of metadata concerns. The compiler would also provide errors at compile-time for required members that are not initialized. That said, it could get messy if you took a class that didn't have required members and added one. It doesn't make sense for the default constructor to exist in that case, which would break existing consumers in a spectacular but not very insightful way. Could leave a default constructor but all it could do is throw that required members haven't been initialized. |
Beta Was this translation helpful? Give feedback.
-
Since the |
Beta Was this translation helpful? Give feedback.
-
This is what I'm doing on data classes. Using named parameters in constructor, the syntax is quite close to object initializers. (
Shouldn't all constructors having the same implicit parameters for initialization?
Currently, nested class in generic inherits outer type parameters, combining with its own defined. It's not about function papameters, but there's a mismatch too. I'm thinking this as best backwards compatibility. The potential conflicting point is parameter names. |
Beta Was this translation helpful? Give feedback.
-
Is the initonly modreq design from #2699 still on the cards? |
Beta Was this translation helpful? Give feedback.
-
I think that could work for both property (for immutable data classes) and collection initializers (for immutable collections). Seems like a unified model for immutable initialization. new ImmutableArray<int> { 1 }
new ImmutableClass { p = 1 }
// delegate initializer to custom builder
new ImmutableArray<int>.Builder { 1 }.Build()
new ImmutableClass.Builder { p = 1 }.Build() Builder can be either compiler-generated or user-defined. |
Beta Was this translation helpful? Give feedback.
-
Builder doesn't solve the situation of consume-change-consume loop. ReadOnlySpan solves this by no-op conversion, but no check about the lifetime. |
Beta Was this translation helpful? Give feedback.
-
@HaloFour Thanks for the creating the issue, I hadn't gotten around to it yet :) |
Beta Was this translation helpful? Give feedback.
-
Right now the proposal is that both the The other approach has me worried about this feature slipping again because we can't design everything without seeing examples and how things work. This moves us forward without really ruling anything out at the moment. |
Beta Was this translation helpful? Give feedback.
-
Also, re: builder pattern -- I couldn't find a way to make it work with inheritance without a lot of problems around either brittleness (moving a field to the base is a breaking change) or duplicating large amounts of state on every inheritance. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
C# Language Design Meeting for Oct. 21
Agenda
Discussion
We'd like to make some progress on records, in both design and implementation. One development in
our view of records is to consider them not as a feature in and of itself, but a shorthand for a
set of features aimed at working with a collection of data. Specifically, we have a proposal to
consider a guiding principle: a record should only be capable of generating code that the user
could write themselves.
To that end, we can look at the set of features we're considering incorporating into records, and
differentiate between them based on the uncertainty of their design. The features which may have
generated behavior are:
Automatic structural equality
With-ers (per type?)
Object initializers for readonly (per member)
Primary constructors + deconstruction
Some features, like with-ers and object initializers, have many open issues. Some
features, like generation of structural equality, have widely agreed upon semantics,
once the set of members that are part of the structure are decided.
It's proposed that we take a subset of the features, namely primary constructors and structural equality, and consider them to have designs ready for implementation. Primary constructors still have open semantic questions, especially around their meaning outside of a records, but all of the proposed records specify some type of primary constructor with very similar semantics. An example of the common semantics would be the following,
which would generate two record members,
Name
andBirthday
, structural equality on those twomembers, and a corresponding constructor/deconstructor pair. The
data
modifier, as well as theprimary constructor, are not necessarily final syntax, but the semantic decisions downstream of
this stand-in don't heavily depend on the specific form of syntax chosen and could be easily
changed.
Conclusion
This looks like a reasonable starting point. Records and the components should
definitely be designed together, to ensure they fit together well, but it's worth
highlighting the more settled pieces as we go.
Init-only
A brief discussion of the init-only fields feature. One clarification: the
init-only properties would be allowed to have setters. Those setters can be
executed in the object initializer, or in the constructor of the object. There
is a proposal to allow them also to be set in the constructors of base types,
which has no opposition at the moment.
There's also a problem with "required" init-only members as currently proposed.
The current design specifies that "required" init-only members (members without
an initializer) would produce an error on the construction side if the member
is not initialized in an object initializer.
For example,
Unfortunately, the proposed emit strategy for
initonly
members would only providean error in source, not in metadata. If a consumer compiled against a previous
implementation of a type, and a required
initonly
member was added, no error wouldbe provided if the consumer were not recompiled. Instead, the member would silently
be set to the default value.
A simple alternative is to drop "required"
initonly
members entirely. Setting an initonlymember would be optional, as it is for public readonly members today, and if it is not set it
would retain its default value. The recommendation for adding required members would be the same
as it is today: use a constructor parameter, which cannot be skipped.
We could also attempt to repair the situation by lowering the required
initonly
members into constructor parameters, but this seems undesirable for many reasons,
including that it's complex to implement, it risks creating collisions with
constructor overloads with the same type, it creates a mismatch in the number of
parameters between source and IL, etc. It does not seem worth going down this path.
Static lambdas
Static lambdas were elided mostly for time reasons and we're interested in bringing
them back. The main hang-up on the syntax is adding modifiers before the lambda
syntax, but we already crossed that bridge with
async
.The only semantics question is whether or not a static lambda guarantees that the
emitted method will be static in metadata. This is true for static local functions,
but there are some important scenarios, like
extern
local functions, which dependon that and could not be implemented for lambdas. In addition, there have been
numerous performance improvements in lambdas and local functions that have taken
advantage of their unspecified metadata characteristics, and at least one significant
performance optimization for lambdas would be lost by requiring them to be static.
Conclusion
The
static
keyword will be allowed on lambdas and it will have the same capturing rules asstatic local functions. It will not require that the lambda be emitted as static.
Beta Was this translation helpful? Give feedback.
All reactions