Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open questions for field-backed properties #8231

Merged
merged 5 commits into from
Jun 21, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions proposals/semi-auto-properties.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,63 @@ public class Point
- https://github.com/dotnet/csharplang/issues/5563
- https://github.com/dotnet/csharplang/pull/5573#issuecomment-1002110830

### Feature name

Some options for the name of the feature:
1. semi-auto properties
1. field access for auto properties [LDM-2023-07-17](https://github.com/dotnet/csharplang/blob/main/meetings/2023/LDM-2023-07-17.md#compiler-check-in)
1. field-backed properties
1. field keyword

### `field` in property initializer

Should `field` be a keyword in a property initializer and bind to the backing field?

```csharp
class MyClass
{
private const int field = -1;

public object Property { get; } = field; // bind to const (ok) or backing field (error)?
}
```

In the example above, binding to the backing field should result in an error: "initializer cannot reference non-static field".
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there an example where field binding to the backing property would have desirable behavior?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't found an example where binding to the backing field could be used in the property initializer.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If so then why do we recommend making it a keyword? Seems like a breaking change that isn't balanced with a positive scenario.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, if we did make field a keyword in property initializer, I would expect to actually be able to read the field in the initializer if the property is static. I feel like it gets wonky.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got a weirder one, which isn't on the list (and I don't know that I've seen it mentioned elsewhere). What about properties with expression body definitions?

public int X => Increment(ref field);

private int Increment(ref int field) => field++;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah those are property accessors and we expect field to be a keyword in them.

Copy link
Member Author

@cston cston Jun 21, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like the backing field of a static property might be usable in the property initializer.

class MyClass
{
    static object Property { get; } = Initialize(out field);
    
    static object Initialize(out object obj)
    {
        return obj = new Random().Next();
    }
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah that's wonky and not useful IMO (you're already assigning the field, why do you need to be able to otherwise use it?). So put me in for wanting 'field' to just not be a keyword in the initializer, even though it might feel a little confusing when an accessor is using 'field' keyword in the same property.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got a weirder one, which isn't on the list (and I don't know that I've seen it mentioned elsewhere). What about properties with expression body definitions?

@HaloFour This was part of the intended design from the beginning, supporting lazy initialization such as that example and => field ??=. #8069 fleshes out the proposal with examples like these.


### `field` and `value` in event accessor

Should `value` be a keyword in an event accessor?

```csharp
class MyClass
{
private EventHandler _e;

public event EventHandler E
{
add { _e += value; }
remove { _e -= value; }
}
}
```

**Recommendation**: `value` is a keyword within an event accessor.

Should `field` be a keyword in an event accessor, and should the compiler generate a backing field?

```csharp
class MyClass
{
public event EventHandler E
{
add { field += value; }
remove { field -= value; }
}
}
```

**Recommendation**: `field` is *not* a keyword within an event accessor, and no backing field is generated.

### Interaction with partial properties

#### Initializers
Expand Down