dotnet / csharplang

The official repo for the design of the C# programming language
11.48k stars 1.02k forks source link

Proposal: Expression property should have a better implementation #1278

Closed heku closed 6 years ago

heku commented 6 years ago

Because below two expression properties are same.

public int PropertyName => _field;
public int PropertyName { get => _field; }

// both generate code
public int PropertyName
{ 
    get { return _field;} 
}

For one target, you introduced two expression syntax for it, it's a little waste. So why don't change the first one to generate below code

public int PropertyName => _field;
// better to generate code below?
public int PropertyName
{
    get { return _field;}
    set { _field = value;}
}

In this way, we can easily wrap some internal fields with a clean way.

class Wrapper
{
   private InternalObject _internal;
   public xxx PropertyWrapper => _internal.InternalProperty;
}

How do you think?

stakx commented 6 years ago

Backwards compatibility is an obvious issue here. By now there's probably a lot of user code out there that assumes => as in your very first example will give you a read-only property. Given the proposed change, these would suddenly become writable next time the code gets recompiled.

yaakov-h commented 6 years ago

I agree with @stakx.

There was another proposal that advocated for something like the following:

public int PropertyName <=> _field;

Unfortunately, I can't find that issue.

heku commented 6 years ago

I know this would be a break change, I just think of why not design it like this before.

theunrepentantgeek commented 6 years ago

I suspect that it's for consistency. Both of these are valid uses:

public string FullName => _fullName;
public string CurrentCity => CurrentAddress.City;

It would be very odd for the first one to define a read/write property but the second to define read/only.

Plus, the => operator is used elsewhere to specify a single expression (or block) on the righthand side; it makes sense for a property definition using => to parallel other forms that use a single expression.

heku commented 6 years ago

@theunrepentantgeek I didn't mean generate different code, for your example, both generate read/write for them. And it makes sense for your other comments.

stakx commented 6 years ago

@yaakov-h:

There was another proposal that advocated for something like the following:

public int PropertyName <=> _field;

Unfortunately, I can't find that issue.

See https://github.com/dotnet/csharplang/issues/1227#issuecomment-354489345, which links to two other issues mentioning <=>.

yaakov-h commented 6 years ago

I just think of why not design it like this before.

If you were going to design => to generate both setters and getters, then how would you design a readonly property as it exists today?

heku commented 6 years ago

Maybe

public xxx Property { get => xxx; }
// or 
public xxx Property { get; } => xxx
DavidArno commented 6 years ago

Given that => already represents a read-only property, And given that changing that to a read/write property would be a massive breaking change, And given that there already exists a proposal to use the <=> syntax to represent a read/write property,

What actually is the purpose of this issue?

gafter commented 6 years ago

Recently, we have been working on a number of language changes to make it easier to program with immutable data. Part of the strategy is to make new shorter shortcuts for readonly properties. If the syntax for a read-write property is shorter than the syntax for a read-only property, then we have failed, and the changes would not encourage programming with immutable data as we intended.

heku commented 6 years ago

Thanks all, I opened this just because the idea came into my mind, maybe the title should be changed to “discussion:is it better to ...”. As this is a breaking change, I close this discussion.

jnm2 commented 6 years ago

@gafter

Recently, we have been working on a number of language changes to make it easier to program with immutable data.

🎉 Interested in details!

gafter commented 6 years ago

@jnm2 Things like expression-bodied members, pattern-matching, readonly struct, records, and tuples.

ghost commented 5 years ago

I found another solution:

public int NewYork {get; set; } using this["NewYork"];

Which is a shortcut for:

public int NewYork
{
   get => this["NewYork"];
   set => this["NewYork"] = value;
}

This also allows:

   public int Age {get; set; } using _age = 10;

Which is a shortcut for:

int _age = 10;
public int Age
{
   get => _age;
   set => _age = value;
}

which gives you access to the backing field _age.

heku commented 4 years ago

Maybe extend the ref's usage is better:

public int this[int index] ref _source[index]; 
public int Prop ref _field;