This project is read-only.

Property without surrogate field

Topics: C# Language Design
Aug 22, 2014 at 7:54 AM
In order to reduce field declaration, I would like to suggest a feature on properties. A common property with logic usually uses a twin field to store and read its real value. Would be nice if C# could avoid this, by using it's own property to process the code logic, something like the auto-property, which does not require twin field.

For example, the common usage of property with some logic:
private int _x;
public int X
{
    get { return _x + 1; }
    set { _x = value - 1; }
}
The dream:
public int X
{
    get { return itself + 1; }
    set { itself = value - 1; }
}
Where "itself" is a sample of keyword which represents the property itself, without the surrogate field.
Aug 22, 2014 at 9:49 AM
In your example since you don't have access to the backing field outside the property you might as well store the incremented value and use the upcoming auto-property initializer to set the initial value to 1.
Regardless there could be more complex expressions with side effects involved. There are already some ideas around for a construct that is halfway between an auto-implemented property and a full property with backing field, you might want to take a look:
https://roslyn.codeplex.com/discussions/561015
https://roslyn.codeplex.com/discussions/550266
Aug 22, 2014 at 5:23 PM
Edited Aug 22, 2014 at 5:23 PM
In many cases we don't need the backing field outside the property. The sample lesliemarshall wrote in those links is a common case where the backing field isn't necessary outside its property: To call PropertyChanged in MVVM pattern.

To simple call a PropertyChanged method when the property receives a "Set", implies in creating a backfield for this property, just to do the following:
private string _userName;
public string UserName
{
    get
    {
        return _userName;
    }
    set
    {
        _userName = value;
        PropertyChanged("UserName");
    }
}
I don't think auto-property initializer can make this same code works without its backfield _userName.

And in this case, _userName isn't necessary outside the property. I could just work directly with UserName.

Of course, if I do want to access the property backfield outside the property, to set its value without raising PropertyChanged for example, then I can use the old fashion way to do this just fine. Or (and this is a new suggestion) use some property's property to access the field, like: UserName.Itself = "some text"; and this wouldn't raise the "set" trigger of the property.

The problem are the other 90% cases which the backing field is just a C# limitation for implemented properties.

The delegate approach suggested by lesliemarshall is a way to avoid this backing field, but it produces much mode code to execute simple things, like raising the PropertyChanged event.

In this suggestion, this new sample would look like this:
public string UserName
{
    get
    {
        return itself;
    }
    set
    {
        itself = value;
        PropertyChanged("UserName");
    }
}
This is much cleaner to read and understand what the code does, for a property that has implementation, but does not require its underling field to be exposed for manipulation.

The example where a Notifier is attached to the property is also nice, for the cases where one single notifier can be applied to many properties. Which is the case of the PropertyChanged event notifier. But for some cases, creating a own Notifier just to handle the specific logic of a specific property wouldn't help either.
Aug 22, 2014 at 7:51 PM
Edited Aug 22, 2014 at 7:59 PM
I agree with this approach, or similar.

So what specific problem does it solve? Too often do I see patterns like this:
private Foo[]_foos;
public Foo[] Foos 
{
    get { return _foos; }
    set 
    {
        _foos = value;
        PropertyChanged("Foos");
    }
}

...

public void ClearFoos()
{
    _foos = new Foo[0];
    // Forgot to fire PropertyChanged!
    // Should have been:
    // Foos = new Foo[0];
}
Perhaps ClearFoos() was written by a different developer. But using almondega's suggestion, there would be no separate _foos field. This would help the original designer enforce that Foos is the only way to manipulate the data.
Aug 22, 2014 at 7:55 PM
Edited Aug 22, 2014 at 8:08 PM
A different syntax may be a bit more repetitive but could allow for more interesting scenarios, such as having a differently typed inner field:
public int X
{
    Stack<int> x;
    get { return x.Pop(); }
    set { x.Push(value); }
}
Or, even multiple inner fields:
public string Info
{
    string info;
    int invocationCount = 0;
    get { return info); }
    set
    { 
        info = value;
        if (invocationCount % 10 == 0)
        {
            Log($"Info written {invocationCount} times.")
        }
    }
}
Aug 22, 2014 at 8:08 PM
(And I am aware, the previous post has a bug where it doesn't increment, but for some reason code blocks replace the + symbol with &43; )