Closed bondsbw closed 1 week ago
@jnm2 Actually, the problem with your solution is this:
bool _active, _dead;
public event EventHandler Foo
{
EventHandler fooActive, fooInactive;
add { if(!this._dead) { if(this._active) fooActive += value; else fooInactive += value; } }
remove { if(!this._dead) { if(this._active) fooActive -= value; else fooInactive -= value; } }
}
What would this.Foo(this, EventArgs.Empty)
raise in this case?
I'd rather a raise
accessor than a get
accessor. A get
accessor would leak the details of the underlying publisher, which might not even be a delegate of the type of the event. A raise
accessor would hide that detail behind a method of a signature matching that delegate.
That assumes that scoped fields make sense in the case of events, and I'm not really sure that they do. It's extremely niche to explicitly implement an event as it is.
Is there a way to vote to advance this proposition? So often I have felt guilty about creating private fields that should never be manipulated outside of Property accessors. I know it's wrong to put them in scope to trip up a maintainer, but the language currently gives us no alternative!
@CharlesJenkins Yes. Vote here:
@CharlesJenkins Yes. Vote here:
Thanks! I hope I got the right one.
Property-Scoped Fields
(Ported from dotnet/roslyn#850)
Summary
Allow fields to be scoped within the accessor body of a property or event declaration.
Motivation
Properties often encapsulate constraints on field access or ensure that certain behaviors are invoked. Sometimes it is appropriate for all field access to be performed through the property, including those from within the same class.
These constraints may be unclear or forgotten, leading to subtle bugs during maintenance which are often difficult to diagnose.
Scoping fields to the body of their property/event would allow the designer to more effectively communicate this intent to encapsulate.
Detailed design
Property-scoped fields may be defined above the accessor list within the body of a property or event:
myField
andhandler
are encapsulated within their respective property/event. In each case, both accessors may directly reference the fields. Nothing outside of the property/event scope has direct access to those fields.Implementation comments from @CyrusNajmabadi:
Alternatives
Automatic backing field
This implementation would be an extension of automatic properties. The backing field could be accessed through a keyword
field
, but only within the scope of the property/event:This would not allow multiple fields to be encapsulated in the same property.
dotnet/roslyn#7614 has a similar proposal with a different keyword (
$state
).Auto-property syntax for custom setter/getter logic
dotnet/roslyn#1551
Semi-auto-properties with setters
dotnet/roslyn#8364
Class-scoped blocks for fields / explicit field usage
dotnet/roslyn#12361
Unresolved questions
A list of questions from @CyrusNajmabadi:
Syntax
It was noted that adding fields above accessors or below accessors (but not interspersed) could be an easier change to the existing compiler design. @lachbaer provided a potential design which would not be a breaking change to the API:
Field name collisions
Should a property-scoped field be allowed to have the same name as another class member?
Should local identifiers within accessors be allowed to have the same name as a property-scoped field?
Design Meetings