@property fields

Quirin Schroll qs.il.paperinik at gmail.com
Thu Jan 16 00:47:47 UTC 2025


On Tuesday, 3 December 2024 at 23:50:20 UTC, Richard (Rikki) 
Andrew Cattermole wrote:
> The ``@property`` attribute has been left in the lurch for 
> quite some time, where only one behaviour related to its return 
> value being of any value.
>
> There are two parts of this proposal, however I am only 
> confident in the first part, fields.
> The other is for methods which would give you full control over 
> it.
>
> Syntax is quite simple:
>
> ``@property int field;``
>
> It is valid in interfaces, structs, and classes.
>
> ```d
> interface IField {
>     @property int field;
> }
>
> class Thing : IField {
>     @property int field;
> }
>
> struct Thing2 {
>     @property int field;
> }
> ```
>
> It results in three things.
>
> 1. A field that is either ``protected`` (classes) or 
> ``private`` (structs).
>
>     ```d
>     class Thing : IField {
>         protected int field;
>     }
>
>     struct Thing2 {
>         private int field;
>     }
>     ```
>
>     If we have struct inheritance, then it would be 
> ``protected`` instead.
>
> 2. It will generate a method for classes and structs in the 
> form:
>
>     ```d
>     class Thing : IField {
>         protected int field;
>
>         ref typeof(this.field) __property_field() /* inferred 
> attributes */ {
>              return this.field;
>         }
>     }
>
>     struct Thing2 {
>         private int field;
>
>         ref typeof(this.field) __property_field() /* inferred 
> attributes */ {
>              return this.field;
>         }
>     }
>     ```
>
> 3. A method stub is generated for the property field in an 
> interface:
>
>     ```d
>     interface IField {
>         ref typeof(this.field) __property_field();
>     }
>     ```
>
>     You may place attributes around the field to apply to the 
> method.
>
>     ```d
>     interface IField {
>         @safe:
>         @property int field;
>     }
>     ```
>
>    This allows an interface to require that a field exists, 
> without defining one. Since it is the stub that gets inherited 
> (which can only be implemented using an ``@property`` field.
>
> Semantically:
>
> 1. You will not have direct access to the field outside of the 
> type. All accesses and mutation will go through the method.
> 2. It may be passed to a function parameter that is ``ref`` or 
> ``out``. This is perfectly safe so needs no protection due to 
> it implicitly being ``scope``.
> 3. An invariant will be called following mutation or when it is 
> passed to a ``ref`` or ``out`` function
> parameter.
>     3.1. For interfaces if a ``@property`` field is used, an 
> invariant will be required to be in the vtable implicitly.
> 4. In ``@safe`` code:
>     4.1. It may not be stored in a ref variable ``ref var = 
> thing.field;``
>     4.2. It may not have a pointer taken to it ``&thing.field``
>
> As long as the invariant is called after mutation, this covers 
> the use case of setter methods for properties. It cannot be 
> used to transform, but will cause errors. If you need 
> transformation wrapping the field with a struct could introduce 
> such behaviors so need not be provided at this level (although 
> it should be supported with ``@property`` methods).

This reminds me of [this C# 
proposal](https://github.com/dotnet/csharplang/blob/main/proposals/field-keyword.md). You’re proposing something quite similar, just the other way around. Your idea is to define the backing field and annotate it to request the getter and setter be defined.

TL;DR: The C# proposal adds a contextual `field` keyword that, 
when used in the getter or setter of a property, refers to an 
implicitly generated backing field.


More information about the dip.ideas mailing list