Replies: 27 comments
-
Were there any thoughts around the use of |
Beta Was this translation helpful? Give feedback.
-
Nothing new from last time. However, the sentiment last time was that the ability to do this was viewed as a significant positive to the |
Beta Was this translation helpful? Give feedback.
-
One more question about |
Beta Was this translation helpful? Give feedback.
-
Call it the "double tap" operator? |
Beta Was this translation helpful? Give feedback.
-
I think it's great that property-scoped fields (#133) are getting attention. The asks leading to the The 95% case for me looks like this: private SomeType someProperty;
public SomeType SomeProperty { get => someProperty; set => Set(ref someProperty, value); } That's two lines and two manually synced names across four rename spots. Property scoping gets rid of the public SomeType SomeProperty { SomeType someProperty; get => someProperty; set => Set(ref someProperty, value); } I wouldn't want to go from two to six lines per property, so I won't even write that out here. This would be my ideal: public SomeType SomeProperty { get; set => Set(ref field, value); } It sounds like this might happen no earlier than C# 11. That's a long wait for something that has accrued as much feedback as #140. I'm happy that the discussion is happening though! |
Beta Was this translation helpful? Give feedback.
-
For me the 95% case is "set the backing value, and also...". Since the "also" can happen either before, or after setting the value I am rooting for delegated properties. |
Beta Was this translation helpful? Give feedback.
-
I'm totally in favor of #133 over #140 or #2657 though they are certainly not contradictory from each other at all. A weak version of #2657 is coming in .net 5 with the additive compiler functionality. I suspect it will not hit the syntax that would be ideal but it will be better than nothing. #133 would appreciatively widen the net of safely falling into the pit of success using C#. The benefit is not "property scoping saves you from typing #140 merely saves you a little bit of typing over #133. It could do more though by saving a slot when inheriting I think in some circumstances? |
Beta Was this translation helpful? Give feedback.
-
@bbarry For a safety net in the meantime that's just for INPC, you might be interested in https://www.nuget.org/packages/PropertyChangedAnalyzers. It's quite sharp. |
Beta Was this translation helpful? Give feedback.
-
The vast majority of my cases fit into:
Though not |
Beta Was this translation helpful? Give feedback.
-
How does that usage look like? I do not use private readonly Lazy<SomeHeavyClass> _someProperty;
public SomeHeavyClass SomeProperty => _someProperty.Value; The backing field assignment might happen in the constructor may happen in the constructor or directly next to the declaration. Doing the same with #133 public SomeHeavyClass SomeProperty
{
private readonly Lazy<SomeHeavyClass> _field = ...;
get => _field.Value;
} needs more lines and a few keystrokes less. Plus, you cannot assign the backing field in the constructor. In ReactiveUI there is a |
Beta Was this translation helpful? Give feedback.
-
@jnm2, to be fair, you could always use the same name for the backing field. For example public SomeType SomeProperty { SomeType field; get => field; set => Set(ref field, value); } You still have to manually snyc the type, though. |
Beta Was this translation helpful? Give feedback.
-
I've used this pattern many times: public IEnumerable<Item> Items
{
get => _items;
set
{
_items.Clear();
if (value != null)
{
_items.AddRange(value);
}
}
}
private readonly List<Item> _items = new List<Item>(); Publishing the property as |
Beta Was this translation helpful? Give feedback.
-
It would look like this: public SomeHeavyClass SomeProperty
{
Lazy<SomeHeavyClass> _someProperty;
get => _someProperty.Value;
} It's longer, but nicely scopes things so that other code doesn't use the backing field inappropriately. |
Beta Was this translation helpful? Give feedback.
-
@CyrusNajmabadi Often Lazy<T> instances are initialized in the constructor because field initializers can't reference |
Beta Was this translation helpful? Give feedback.
-
@quinmars That's an excellent point that I hadn't considered. The scoping actually does let me get away from maintaining a second name. Thank you! |
Beta Was this translation helpful? Give feedback.
-
@theunrepentantgeek, good point! I haven't thought about that. With #140 you could write public IEnumerable<Item> Items
{
get;
set => field = value.ToList();
} But I acknowledge that this shows a slightly different behaviour. I'm not decided if that is better or not. |
Beta Was this translation helpful? Give feedback.
-
@jnm2, you're welcome! |
Beta Was this translation helpful? Give feedback.
-
@quinmars I think you mean #140 for #3615 (comment)? |
Beta Was this translation helpful? Give feedback.
-
Indeed, corrected. Thank you. |
Beta Was this translation helpful? Give feedback.
-
Due to the issue @jnm2 raised and to avoid making many instances of |
Beta Was this translation helpful? Give feedback.
-
In my opinion, an attribute approach is superior to unwieldy [Handler]
class N : Attribute {
public static void Handle<T>(T o, [CallerArgumentExpression(nameof(o))] string name = null) where T : class? {
if (o is null) throw new ArgumentNullException(name);
}
} public void M([N] Chitty chitty)
{
}
// ->
public void M([N] Chitty chitty)
{
N.Handle(chitty);
} You can define your own logic or make it |
Beta Was this translation helpful? Give feedback.
-
We considered this and it was soundly outvoted by all the participants fwiw. |
Beta Was this translation helpful? Give feedback.
-
This is a good point and having a "conventional" identifier for the backing field would definitely be a benefit, negating problems with refactoring property / field names. I think the argument for property-scoped fields is well made in the LDM notes, particularly in the case of backing fields of differing types to the property, but I'm also encouraged (because I still think there is a lot of use where simply using an automatically generated ... which leads me to wonder what will happen to #140 if property-scoped fields are implemented ahead of #140 and developers start writing all their code with |
Beta Was this translation helpful? Give feedback.
-
If |
Beta Was this translation helpful? Give feedback.
-
@BobSammers It wouldn't change the fact that #140 already requires binding |
Beta Was this translation helpful? Give feedback.
-
Nod, if #140 is implemented based on property-scoped fields the compiler would still have to recognize the difference between the two: public class C {
public string field;
public string Prop1 {
string field;
// references property-scoped field
get => field; set => field = value;
}
public string Prop2 {
// references class field
get => field; set => field = value;
}
} |
Beta Was this translation helpful? Give feedback.
-
Yes, @jnm2 and @HaloFour, you're both right, of course, it shouldn't change anything. |
Beta Was this translation helpful? Give feedback.
-
https://github.com/dotnet/csharplang/blob/master/meetings/2020/LDM-2020-06-24.md
Agenda
Beta Was this translation helpful? Give feedback.
All reactions