# C# Language Design Meeting for April 20, 2020 ## Agenda Records: 1. Factory methods ## Discussion The proposal at its core is to allow certain methods to opt-in to certain language semantics that are only currently valid at construction, namely object initializers, collection initializers, and the new `with` expression (although that expression is legal on only certain factory methods). Possible extension of the feature: allow initializer forms everywhere, but only allow `init` properties to be initialized when the method is marked with `Factory`. However, almost all uses of this syntax would be a mutation of the receiver, and it may not be clear that the initializer syntax produces a mutation. As to whether `null` should be a valid return: most people think no. Since almost all initializer forms dereference the receiver, this is essentially creating a very obscure way of producing exceptions. In addition, all struct values should be permitted, as they are all safe. `default` should be legal if the target type is known to be a struct. We have not considered what the behavior should be for unconstrained generics. There also some concerns about the syntactic extensions. First in that this would make `identifier { ... }` a valid syntactic form in most situations. This may not be syntactically ambiguous today, but we have a lot of different features, like `block expressions`, which share some syntactic similarity. Even if there is no syntactic ambiguity, some people are still concerned that the feature will be too opaque. One way to remedy this would be to require the `new` keyword for this form as well. So the new syntax would be: ```C# var s = new Create() { Name = "Andy" }; ``` There could be some naming ambiguity here because `Create` could be either a factory method or a type name. We would have to preserve the interpretation as a type here for compatibility. There's a broader question of how or if we'd like a general initializer feature. There's some question of whether the feature is useful enough to deserve the complexity at all, using any additional syntax. Alternatively, we could embrace the syntax requiring the `new` keyword. One important piece of history is that initializers are not meant for mutating existing state, only for mutating new objects. This doesn't necessarily conflict with allowing initializers on any object, but the reason here is not that the language is suggesting using object initializers for arbitrary mutation, but that convention alone is good enough to promote use on "new" objects only. Regardless of the extensions of the feature, we certainly need to implement something for records. The core feature requirement here is for the `with` expression, which needs to assign to `init` fields. We can head two directions: special case the `Clone` method, or build a more general feature. This is a spectrum, where one end may be a new syntactic form specific to just the Clone method, and the other end could be a `Factory` attribute that could be applied to any method. ### Conclusion Right now we're more concerned with what to do for records. In the meantime, let's not support user-written Clone methods. A Clone method will be generated for a record with an unspeakable type and the SpecialName flag. The `with` expression will look for exactly that method name. We intend to decide for C# 9 how that method will be written in source. We'll consider broader `Factory` scenarios later.