Proposal: field
keyword in properties
#8634
Replies: 429 comments 5 replies
-
This could also be useful/part of the implementation for #133. |
Beta Was this translation helpful? Give feedback.
-
My opinion is that this proposal makes auto-implemented properties more difficult to read by introducing these silent backing fields despite the use of logic. With expression-bodied accessor members a chunk of the boilerplate for standard properties already disappears. The IDE eliminates much of the rest via standard code snippets. |
Beta Was this translation helpful? Give feedback.
-
Suggestion:
int ASemiAutoProp
{
get;
set
{
var pcea = new PropertyChangeEventArgs(this.ASemiAutoProp, value));
OnPropertyChanging( pcea );
yield return value;
OnPropertyChanged( pcea );
}
} Then there is no need for a new And the following really looks better than with #133 public T PropertyInitialized
{
get;
set => value ?? new ArgumentNullException();
} = default(T); instead of (with #133) - a bit much of public T PropertyInitialized
{
T backingField = default(T);
get => backingField;
set => backingField = value ?? new ArgumentNullException();
} |
Beta Was this translation helpful? Give feedback.
-
Instead of using a public string FirstName
{
get;
set => _name = value;
} _name;
In case expression-bodied public string FirstName
{
get;
set => value;
} _name = "(not set)"; This completely eradicates the need for a public string FirstName
{
get;
set {
var pcea = new PropertyChangeEventArgs(_name, value));
OnPropertyChanging( pcea );
_name = value;
OnPropertyChanged( pcea );
}
} _name = "(not set)"; This would also go hand in hand with #133. |
Beta Was this translation helpful? Give feedback.
-
With the declaration of the field being outside of the property block that would imply that the scope of that field would be for the entire class, not for just that property. That's also consistent with the scoping of that C syntax. |
Beta Was this translation helpful? Give feedback.
-
@HaloFour |
Beta Was this translation helpful? Give feedback.
-
Of course specifying a getter only works, too: public string FirstName
{
get {
Debug.Assert( _name != null, "Getting name before setting it?");
return _name;
}
set;
} _name = null; or combined: public string FirstName
{
get {
Debug.Assert( _name != null, "Getting name before setting it?");
return _name;
}
set => value ?? throw new ArgumentNullException();
} _name; In the latter example, just specifying the |
Beta Was this translation helpful? Give feedback.
-
I don't disagree with your whole comment, but I wanted to point out that the difficulty reading is only if you're accustomed to thinking of logic and automatic backing fields as mutually exclusive. I don't think they should be. It's not hard to learn to look for a The reason I really like this proposal is not because it enables me to write less code, but because it allows me to scope a field to a property. A top source of bugs in the past has been inadequate control over direct field access and enforcing consistent property access. Refactoring into multiple types to add that desirable scope is quite often not worth it. To that end, a Not infrequently I'm renaming constructs such as this, where private bool someProperty;
public bool SomeProperty { get { return someProperty; } private set { Set(ref someProperty, value); } } This kills two birds with one stone: 1) scope safety, 2) more DRY, less maintenence: public bool SomeProperty { get; private set { Set(ref field, value); } } |
Beta Was this translation helpful? Give feedback.
-
/cc @CyrusNajmabadi |
Beta Was this translation helpful? Give feedback.
-
Meanwhile some time went by. I'd like to state my opionion on the questions from the inital post. Allow both accessors to be defined simultaneously?Yes, definitely. A nice example is the sample at the end of this comment. A semi-auto-property with an implicit
Assing expression bodied setters? and Assign block body with return?I'd like to have that, because simply it looks nice and would totally fit into how "assign-to"-return expressions look. But introducing to much new behaviour and especially having the compiler and reading user to differentiate between return and non-returning bodies can be confusing. Therefore I'd go with "no" on this currently. Prohibit field keyword if not semi-auto?No, but it must not be highlighted by the IDE in that case, because it that context it is no keyword anymore. I think it is very unlikely that somebody converts a semi-auto-property to an ordinary property and simultaneously has a 'field' named field in scope. If property-scoped fields become availble shall that feature be available for semi-auto-properties as well?Yes, if any possible. SAPs allow both, getter and setter, to be defined. It would make sense to make no difference versus normal properties to restrict that feature. |
Beta Was this translation helpful? Give feedback.
-
Taken from @quinmars at #681 (comment), this feature would allow devs to write a 1-liner to implement lazy initialization: public T Foo => LazyInitializer.EnsureInitialized(ref field, InitializeFoo);
private T InitializeFoo() { ... } |
Beta Was this translation helpful? Give feedback.
-
@jamesqo Except using this LazyInitializer method has a downside (unless the initializer method is static) because you'll be creating a delegate instance each time the property is accessed. What you want to write is: public T Foo =>
{
if (field == null)
{
System.Threading.Interlocked.CompareExchange(ref field, InitializeFoo(), null);
}
return field;
}; And now its not really a one-liner. |
Beta Was this translation helpful? Give feedback.
-
@mattwar Well they said they intend to cache point-free delegates eventually. Also what if people don't care about extra allocations because the initializer is doing something like network I/O which completely dwarfs allocating a few extra objects? |
Beta Was this translation helpful? Give feedback.
-
However the |
Beta Was this translation helpful? Give feedback.
-
@lachbaer why? |
Beta Was this translation helpful? Give feedback.
-
You can declare it. We don't require The same is true for |
Beta Was this translation helpful? Give feedback.
-
The data showed it was tremendously more breaking. See https://github.com/dotnet/csharplang/blob/main/meetings/2024/LDM-2024-07-15.md#field-keyword for the meeting decision on this. |
Beta Was this translation helpful? Give feedback.
-
@UniqeId6542 That's what we tried first, but GitHub data showed it broke too much code, so we had to dial it down. |
Beta Was this translation helpful? Give feedback.
-
A bit of a tangent, but has the team considered creating auto-fixers like |
Beta Was this translation helpful? Give feedback.
-
I believe you, but I am curious what cases are people declaring a local variable "field" in a property body then not accessing it? Or were people already using a @ in uses of the field but not the declaration? |
Beta Was this translation helpful? Give feedback.
-
Perhaps I'm not understanding the idea wrong, but it looks like there's more than just a backing field being synthesized. |
Beta Was this translation helpful? Give feedback.
-
@Boomkop3 what else do you see synthesized there? All i see is a synthesized backing |
Beta Was this translation helpful? Give feedback.
-
@CyrusNajmabadi I am seeing |
Beta Was this translation helpful? Give feedback.
-
the property initalizer " = null!" is not part of the setter, it will be set as the initial value of the backing field. |
Beta Was this translation helpful? Give feedback.
-
Yes. That assigns to the backing field (just like a normal auto prop today). For example: That didn't change with |
Beta Was this translation helpful? Give feedback.
-
@CyrusNajmabadi ah, you're right, that's just for initialization. It's quite obvious now that I look at it again. Thank you! |
Beta Was this translation helpful? Give feedback.
-
Have you considered giving the class access to the fields of other properties? I have on occasion needed to have one property's |
Beta Was this translation helpful? Give feedback.
-
Is this language version currently planned to be released as GA along side .NET 10 or will we potentially see it earlier? |
Beta Was this translation helpful? Give feedback.
-
Proposal:
field
keyword in properties(Ported from dotnet/roslyn#8364)
Specification: https://github.com/dotnet/csharplang/blob/main/proposals/field-keyword.md
LDM history:
Beta Was this translation helpful? Give feedback.
All reactions