Replies: 26 comments
-
@CyrusNajmabadi I just fixed it. |
Beta Was this translation helpful? Give feedback.
-
Strongly agreed. For me the most important aspects of records is that I can write something in one line as short as:
I don't want records to be built of separable features because I would almost never use them. There's so many options once we step out of record land that it needs to be user customizable, and source generators seem the perfect way to do that. |
Beta Was this translation helpful? Give feedback.
-
I have never seen the "validator" feature design. Is it mentioned anywhere? |
Beta Was this translation helpful? Give feedback.
-
@qrli |
Beta Was this translation helpful? Give feedback.
-
Also, @agocke, thanks for putting up the meeting notes so quickly - it's really appreciated! |
Beta Was this translation helpful? Give feedback.
-
Please consider allowing the use of |
Beta Was this translation helpful? Give feedback.
-
And I think this is absolutely fine. People who need sequence equality for list members can either override |
Beta Was this translation helpful? Give feedback.
-
Thanks for the link @YairHalberstadt After reading that, I feel the considered use cases for "validators" may be a bit less than I expected. Maybe it is the name, but to me it is not just "validators". It may also do:
I'm not sure whether current "validator" design allows modifying init-only fields. If it allows, it could be fine. |
Beta Was this translation helpful? Give feedback.
-
I definitely like the ability for “validators” to be able to precompute or modify input variables. |
Beta Was this translation helpful? Give feedback.
-
In the last LDM we discussed not calling these 'validators' and instead just reusing the 'init' keyword in a manner like this:
This would basically just be code that runs after the constructor runs. It would be able to do anyting that the constructor would normally be able to do (validate, compute, assign, cache, etc.). IIRC, this was viewed highly positively. |
Beta Was this translation helpful? Give feedback.
-
That's cool. |
Beta Was this translation helpful? Give feedback.
-
How would this work with inheritance? Could I use an object initialiser for a derived class that assigns properties to both base and derived classes? And could the validators then be automatically called in order, base class validator then derived class validator, to run any post-init checks/updates? If so that would be really powerful.... in fact would such use of object initialisation and validators potentially remove the need for constructors and allow a very clean inheritance system without constructor chains? |
Beta Was this translation helpful? Give feedback.
-
Similar to constructors, it would likely have to call into the base type to init.
Yes.
I don't see it being any cleaner/less-clean than constructors. They're supposed to be effectively isomorphic. Just one allows you to initialize directly after the object creation, one requires inside the creation. |
Beta Was this translation helpful? Give feedback.
-
I see. I was hoping the compiler could automatically call the base class 'validator' before the derived class 'validator' as an improvement on how constructors work. I'm hoping in future this records feature can extend to allowing multiple groups of properties to be easily combined/composed (i.e. simple multiple inheritance) which would be very convenient for building up data objects. Wouldn't automating validator calls to the base class help keep things clean and reduce boilerplate as well as simplifying a future extension to support multiple inheritance? |
Beta Was this translation helpful? Give feedback.
-
yes. that's what i meant :) users would not control this. it would be like a destructor. the base destructor is getting called automatically :) |
Beta Was this translation helpful? Give feedback.
-
Sounds great and a lot cleaner than having explicit If you go the route of property-level construction/destruction with optional post-constructors (validators) for whole object validation etc, would it also make sense to have optional pre-destructors for whole object tasks such as cleanup or logging the removal of an object? These would be symmetric to the validators and called in the opposite order (derived class pre-destructor then base class pre-destructor). I really like the idea of automatically called whole-object post-constructors/pre-destructors.... with the compiler handling calls up and down the inheritance chain.... |
Beta Was this translation helpful? Give feedback.
-
The only "destructor" in C# is finalizers. I don't think any change to how finalizers work is currently on the table. Personally, I find finalizers a pretty rough part of the language and would prefer we not modify that area any more than necessary. |
Beta Was this translation helpful? Give feedback.
-
Okay, I think I mis-understood something I read about records and property-level destruction (which I was curious about). But anyway as @CyrusNajmabadi mentioned, destructors/finalizers already are automatically called up the inheritance chain. One final question (thanks for the illuminating discussion): I assume there will be a compiler warning if an object initializer omits a property that lacks an explicit default? (i.e. use of unspecified default values is assumed unintended). It seems to me use of C# language default values where not specified by the programmer can often conceal bugs and is not massively compatible with nullable reference types. |
Beta Was this translation helpful? Give feedback.
-
You don't need explicit |
Beta Was this translation helpful? Give feedback.
-
Thanks, apologies for my error. |
Beta Was this translation helpful? Give feedback.
-
I was playing with the proposed
As mentioned, the only way to read the property is to invoke the getter accessor directly, but this creates another problem as C# does not allow you to directly invoke accessor methods for properties that it can support. So if someone were to work around this problem by calling I don't know if there is another way to apply the Weirdly enough this behavior is not consistent across the ecosystem. VB.NET has no problem reading from the property, for example. And F# completely ignores the |
Beta Was this translation helpful? Give feedback.
-
I would suggest the primary constructor on records replace the default ctor, so arguments would be accessible in the declared constructor. data class Person(string name) {
public Person() {
if (name is null) throw new Exception();
}
} All the other constructors (with args) must either call the primary constructor or another constructor to make sure all fields are initialized. |
Beta Was this translation helpful? Give feedback.
-
I can't agree with replacing the default constructor. I could see us allowing you to leave off the parens entirely to create a body, but validation will likely be done by whatever syntax we choose for validators, which will work for all user-defined types, not just records. |
Beta Was this translation helpful? Give feedback.
-
The above isn't written very well but really my questions here should have been:
It would be really great if we could somehow specify parameters to be "required" in object initialization and then be able to use e.g. non-nullable reference types without artificial default values or compiler warnings.... Any thoughts? |
Beta Was this translation helpful? Give feedback.
-
@markm77 No to both of your questions. Go see the discussion in #2328. |
Beta Was this translation helpful? Give feedback.
-
March 30, 2020
C# Language Design Notes for March 30, 2020
Beta Was this translation helpful? Give feedback.
All reactions