Open AnthonyDGreen opened 6 years ago
Wow, @AnthonyDGreen, your idea is amazing!
The beauty of it, in my opinion, is that:
TrimAttribute
and AutoRoundAttribute
in your exampleIMHO this last point is the strongest, and I think not clear enough in your description -- in your screenshots you handled INotifyPropertyChanged on the type itself, instead of on NotifyAttribute.
Amazing work!
NotifyOnPropertySet
, we should use Notify_OnPropertySet
, to make clear that these are being called by the NotifyAttribute (and the notation is similar to Text1_TextChanged
). Otherwise it reads like a string of words, as if Notify was a verb (and MaxLengthOnPropertySet reads completely senseless)...Notify_OnPropertySet(propName, backingField, value)
in which I have to check propName myself, I would sometimes prefer to handle things in a specific Notify_OnPropertySet_PropName
method. (This would also slightly increase runtime performance, and would also remove the need for generics in this case.)AutoPropertyChangedAttribute
as well that does the work for you in the case if handling INotifyPropertyChanged?@AnthonyDGreen My first impression is that it sounds like a good solution. I'll have to re-read it a few times to let it all soak in, but it's pretty impressive! 😄
@bandleader in your screenshots you handled INotifyPropertyChanged on the type itself, instead of on NotifyAttribute.
That's because it has to be handled on the type and cannot be handled in the attribute. The handler method needs to raise an event, and that can only be done from within the object that "owns" the event (I'm not sure if that's the right terminology). See @AnthonyDGreen's last bullet point before the "Today" section:
The problem is the attribute isn't in the same class as the property and can't raise any events in another object.
@bandleader 1. Word breakup
I have an aversion to underscores in method names, so I prefer the original naming proposal. 😄
@bandleader 2. Property-specific handler methods
I'm just thinking out loud on this one. I can see how this would easily slot into the proposed resolution logic, but is there a benefit to having a property-specific handler, as opposed to just not using an auto-property and putting that handler's logic in the setter? I guess by having the property-specific handler for one particular attribute, you could still specify other attributes and they would be handled using the normal logic. So yeah, I guess this makes sense.
@bandleader 4. Usage with explicit properties
I feel like this would open up a can of worms. If you let it work with "manual" properties, then it's a small step to want it in non-properties as well (subs, functions, custom constructors, event handlers, etc, etc). Maybe that's a good thing, but it feels like feature-creep. The idea works well for auto-properties because the compiler is already generating the body of the methods. This is just telling the compiler how to implement them.
@bandleader 5. Backwards/lateral compatibility
As far as I understand, yes, your assumption that you could consume them from earlier versions is correct. The compiler is simply generating different IL - you could implement the exact same logic yourself by manually calling the handler methods inside a "manual" property.
@AnthonyDGreen one thought that's popped into my head is when you have multiple attributes on a property, what determines the order that the handlers are called in? For example, you've got a TrimAttribute
and a MaxLength
attribute. Ideally you'd want the Trim
attribute to be run first, so that whitespace is removed, allowing it to pass successfully through the MaxLength
attribute (assuming the whitespace made the string too long). Are you simply using the order that the attributes are defined in? I could see that causing some unintended behaviour if things like code formatters are reordering attributes into alphabetical order.
There are much simpler ways to handle AOP like scenarios with INotifyPropertyChanged, and there is no need for heavy language's changes like https://github.com/dotnet/csharplang/issues/107 or https://github.com/dotnet/vblang/issues/194 or anything like that.. The point is that inheritance and polymorphism already allow for such scenarios, but there is missing piece to fully exploit it.
Public Class SomeObj
Public Overridable Property MyProp As Integer
End Class
Public Class SomeObjINPC
Inherits SomeObj
Implements INotifyPropertyChanged
Public Overrides Property MyProp As Integer
Get
Return MyBase.MyProp
End Get
Set(value As Integer)
MyBase.MyProp = value
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("MyProp"))
End Set
End Property
Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
End Class
The problem is that SomeObjINPC must be instantiated everywhere in place of SomeObj, and currently this require changes in code that create SomeObj instances, which is very uncomfortable. To solve it, there must be method (similar to extension methods), that overrides process of creating instances.
Public Function New() As SomeObj
Return New SomeObjINPC
End Function
So, compiler must detect this method, and use it to create instance of returned type.
Dim o = New SomeObj ' Call New function that create SomeObjINPC
Such New generator may also be used for other purposes
@AnthonyDGreen if you agree with @reduckted 's point about order (the order listed) and you don't see implementation issues with that, perhaps include in proposal.
I am also worried about ordering of the in-class code. I may not want to notify if validation fails.
I'm somewhat concerned about returning a boolean. This slants the feature heavily to validation scenarios.
I think there are variations that alleviate these concerns.
I think this is cool and might be an interesting direction.
It feels like a foundation to a more complete set of work. It looks most interesting at first review as a basis for community implementation(s) of a set of meaningful attributes. This keeps individual developers from having to write their own implementations while leaving the implementation very flexible and dynamic.
I don't know how serious versioning problems would be in such a scenario.
@KathleenDollard totally agreed about it being a basis for community implementations. VB thrives when community members can share abstractions with each other to be more productive.
I wanted to try a mix of approaches out so a handler may return a Boolean
or it could just be a Sub
. I also wanted to try exception throwing validation ThrowOnNull
and IDataErrorInfo-style validation, where the user can set bad state and the UI just reports it.
@reduckted yes, the ordering in source is significant. In fact if you can see in my examples I had to put the Notify attribute before most other attributes since that's where I put the code to check for duplicate values. I could have factored that logic into its own handler, I just didn't. But in the case of Trim and ThrowOnNull I put those before Notify because one transforms the value and the other will just throw an exception.
@bandleader @reduckted speaks the True True
, in .NET it's impossible to raise an event from outside of the class that defined it. Not even a derived class can directly raise an event declared on its base class. That's why base classes will usually expose some protected method On<EventNameHere>
that raises the event for derived types. So the only way to make a single attribute to handle INPC would be to ship the attribute with a base class that users could inherit that exposes such a method. It can't even be done with extension methods. In general though, I think every system I've ever written has resulted in me defining my own base classes for common behaviors like this so it's not a loss if the cost of two-way binding goes from once per property to once per program.
Hey Anthony,
My thoughts:
There are VB enthusiasts like us, who would love this feature.
Those enthusiasts would like VB to be as (good/grown up/flexible/Professional/enter your adjective here) as C#. Basically, they are good C# developers, but like the VB Language “taste” better, so they use VB.
And then there is the typical VB developer. He might use attributes, but I’m not sure if he writes them. He might use inheritance, but only “as directed”.
This feature is for the C# VB developer, I think.
It leaves out what feels like 80% of the TYPICAL VB audience, who do not know about when to use more than implicit inheritance (when creating a new WinForms form, e.g) or when to write custom attributes. And they should not need to know.
So, as a voice for them I have to say: this feature is not for VB. It is WAY too complicated to use.
I, however, would love it.
Klaus
@KlausLoeffelmann
If there was a VBContrib library, do you think it could have attributes available for use that the typical VB developer could embrace?
That is where I see the potential value of this feature.
I totally agree with @KlausLoeffelmann. The typical VB.NET developer may not know (or care) about such a feature. It's those advanced VB.NET developers that are likely to implement and use this.
Being in the advanced group, this concept is very appealing but I can't help but wonder if beginner and lower intermediate level developers will have the same level of interest.
@AnthonyDGreen
Would it be possible to include a 'precedence' property in the attributes? That way the compiler/parser can determine the order of execution of the associated code. If not then the method associated with a custom attribute could end up being called at the wrong time.
@AnthonyDGreen
I am concerned about the backing field. Take the case in #279
You don't use the backing field, but you'd still like to use validation features and mutating features like your Trim and AutoRound.
I'm imagining a VBContrib style library that had people inherit from a ViewStateWrapper class and add attributes. How would they know that these attributes didn't work, or is there a way to make them work?
Kathleen
@KlausLoeffelmann - I think you insult VB.Net developers by suggesting that the good ones are actually just good C# developers looking for variety. I would argue that the best C# developers are actually just good VB developers investigating what all the fuss is about... :)
Getting back on topic... I think this exactly the kind of thing that might encourage some of those 'typical' VB developers you refer to, to expand their horizons into the wonderful world of attributes, especially if there are handy libraries of helpers to ease their way into modern coding patterns, which they could then also more readily embrace (I know the pain of INotifyPropertyChanged has been enough to make me pack up my bags and go home early so that I could psyche myself up for a day of copy, paste and regex-replace....)
@KlausLoeffelmann So, as a voice for them I have to say: this feature is not for VB. It is WAY too complicated to use.
Respectfully disagree. I'm also an advanced VB developer who also uses C#, but even if you're talking about beginners: where they don't understand something 100%, they are fine with copying from StackOverflow and adapting it to their needs. Remember that back in VB6 people were doing amazing things by copying some Win32 API code from PlanetSourceCode or CodeProject!
But secondly, I don't think that VB is a beginner's language. It was never meant to limit developers, but to give them all the power possible as cleanly, beautifully and approachably as possible -- letting them not just start out programming but become master programmers in a syntax that is beautiful to masters, beginners, and laymen alike. That's why MS earlier had VB.NET on feature parity with C#; there's nothing about the language that throws advanced users away -- nor should we have any.
Remember that VB6's popularity was the ability to make (in a fraction of the time and complexity) all the "regular" Windows desktop apps that were popular at the time. Today, people aren't making Windows desktop apps; they're making mobile apps (and some cross-platform and web apps) with MVC/MVVM frameworks. (An imperative WinForms app is simply not competitive today.) Inasmuch as INotifyPropertyChanged is necessary for that, this feature doesn't complicate things; on the contrary, it simplifies implementation of an inteface that is a basic necessity for giving users to power to make today's apps.
@KathleenDollard If there was a VBContrib library, do you think it could have attributes available for use that the typical VB developer could embrace?
I imagine the attributes would go directly into the BCL, because I am sure that other languages (like C#) will eventually want to take advantage as well. This isn't a VB-specific thing; it's a common need to have data classes with reduced boilerplate -- Scala for instance calls them "case classes."
@KathleenDollard I am concerned about the backing field. [...] You don't use the backing field, but you'd still like to use validation features and mutating features like your Trim and AutoRound.
In @AnthonyDGreen's design, the compiler passes the newly-being-assigned value to each attribute as ByRef value
and each attribute could validate and even mutate the value if it desires. They do not have to use the backing field directly.
(In fact, he had mentioned that perhaps the backing field could even be omitted when not necessary i.e. when there's an alternate store -- see his last paragraph here.)
@franzalex Would it be possible to include a 'precedence' property in the attributes?
Why wouldn't we simply do it in the order the attributes were declared?
@AnthonyDGreen In .NET it's impossible to raise an event from outside of the class that defined it.
I propose that we need to find a way around this, whether that means cooperating with the CLR team, or simply using one of the 'hacks' available on the internet -- I did a quick search and found some interesting results. The reason is because with all the talk about supporting first-day-programming beginners, it is indeed hard to expect them to figure out on their own how to create a method with the right name and signature and raise PropertyChanged -- they would want to just declare the NotifyPropertyChanged attribute and be done with it.
@bandleader Why wouldn't we simply do it in the order the attributes were declared?
See my concerns above about code formatters reordering the attributes.
@KathleenDollard : The only way I see this feature would make sense in the original spirit of VB was, if we considered @AnthonyDGreen 's concept to be rather infrastructure, and we put ready to use base classes and/or attributes in the My-namespace. VbContrib lacks discoverability for too many of the VB devs. Since those should be available for .NET Core/.NET Standard, maybe we could have new templates for VS/CLI which then include a VB specific NuGet which would contain an extended My-Namspace for each respective project type.
We need to talk about updating My-Namespace anyway. The infrastructure of the compiler - just in case folks did not know that - already allows that without modifying compiler or framework libs. This would be another great community initiative, btw!
@bandleader : I wouldn't call VB at all an exclusive beginner language, because it is not. Vb is a compromise Productivity vs. Flexibility. I'm just talking about approachabiliy and discoverability. We need new functionality to be picked up by the whole audience instantly. If the majority does not get it on first glance, they cold-shoulder it most probably. We need something which I'd call Guidance by Product. Things must be so intuitive that VB folks pick them up just like that.
Things that made VB6 great were
And later in .NET
Functionality in that spirit can be the only unique selling feature for VB. Parity for everything to C# doesn't make and never made any sense. If I wanted everything like in C#, why wouldn't I take C#: Which is exactly what MILLIONS of devs did. VB had an identity crisis for a long time. We need to find a way to give it back it's own identity, it original self. Otherwise, VB will end up as a boring Zomby, which will only get those things which are needed to consume necessary platform improvements. Like Interface methods.
Klaus
And then there is the typical VB developer. He might use attributes, but I’m not sure if he writes them. He might use inheritance, but only “as directed”.
I don't understand this mentality. We've got a good feature (yes, it could be improved and refined, but it's still good), but just because some developers who use the language wouldn't feel comfortable using it, we must throw it away? Why?
So, as a voice for them I have to say: this feature is not for VB. It is WAY too complicated to use.
No one is forcing them to use it. For those of us who know how to use VB to it's full extent, this is a great idea, and we shouldn't be hamstrung by novice developers for fear of them not understanding it. Documentation and tutorials can help them.
This sort of thinking is, in my opinion, what feeds the hatred and ridicule of VB.NET. The idea that the language is a "beginner language" and therefore must not contain advanced concepts or anything that's too complicated. This feature would be really useful for things like view models in an MVVM-based WPF application. If this "typical VB developer" is creating an MVVM-based WPF application, then surely they can understand this proposed concept.
Maybe I'm just really out-of-step with what a "typical VB developer" is, given that I, and my colleagues at work, are all highly competent VB.NET developers.
@reduckted: Couple of questions:
I am curious about what you and other people think!
First of, I really love this idea. I like it has a hint of extensibility. To me that's a future safeguard, an avenue to deal with change and evolve without having to wait for a new version of VB with yet more keywords to deal with new frameworks or patterns.
I would like to see more detail on how the compiler knows what to inline.
Re typical VB developers... stuff 'em ;) Yes I said that. If they can't speak up for themselves I wonder if they should be programming in the next era. I think the biggest problems VB faces are the lack of community involvement; this notion that we can't have anything extensible because we need defined sandboxes and prescribed buckets and shovels. I don't believe the "average" VB developer doesn't use attributes, rather I believe they use them when they have to, designers, serialization, data contracts, etc. But more importantly I think we need to stop projecting this notion of a VB developer as "hopeless". We need to give them hope, and this feature to me ticks all those boxes. I strongly believe VB needs to grow up and get ready to move out of home.
Completely with @reduckted and @Bill-McC on this one. Yes, Visual Basic is popular among beginners for various reasons, but as I said, why can't they continue to use it even once they're advanced programmers? Isn't that its whole value? The isn't MS's toy language. The goal here is to make it approachable for beginners to get started -- not to omit any feature that beginners will not be able to immediately use and understand.
"VB is as powerful as other languages, but much cleaner, and with much more sugar and elegance." -- A Wise Man
@KlausLoeffelmann Visual Basic is de facto an entry level language. The telemetry proves that. It's fact.
"An entry-level language?" It doesn't prove that the language is unsuited to advanced developers, just that advanced VB developers are frustrated at MS's abandonment of it, and have left for C#.
@KlausLoeffelmann Do you think a feature like that would help to move a C# team back to VB?
This isn't about moving C# teams to VB, but about making each language as great as it can be. We don't need feature differentiators per se; it's a syntax preference. Simple feature parity would go a long way towards making VB viable.
@KlausLoeffelmann If VBs popularity can be improved with features which are for most of the target audience, should we not concentrate of those features, because we only have so much time or money?
That's not what's happening. MS is not improving VB and focusing on beginner-friendly features. They're improving C# and letting VB fall by the wayside.
@reduckted No one is forcing them to use it. For those of us who know how to use VB to it's full extent, this is a great idea, and we shouldn't be hamstrung by novice developers for fear of them not understanding it. Documentation and tutorials can help them. / This sort of thinking is, in my opinion, what feeds the hatred and ridicule of VB.NET. The idea that the language is a "beginner language" and therefore must not contain advanced concepts or anything that's too complicated.
Gold. See also what I wrote above about the amazing ability of beginning programmers' to copy code from StackOverflow (and actually improve their programming skills in the process).
@KlausLoeffelmann Why do you think, I proposed to throw away this features as you wrote?
The impression I got from your comments was that it was too complicated: "this feature is not for VB. It is WAY too complicated to use."
You wrote some developers. I'm interested: What would be your estimation, how many (typical) VB developers would be overwhelmed with @AnthonyDGreen's feature as it is.
I wrote "some" because that's what you said. You said "It leaves out what feels like 80% of the TYPICAL VB audience,". There's your percentage that you wanted. When I wrote "some", I was referring to the 80% that you came up with.
Again: what do you think is the percentage? I am just trying to get a feeling if my estimation is shared by others.
Even if you think this proposal is only for 'advanced' coders, I don't see how you can extrapolate that perspective into "this proposal doesn't belong in VB, because it's too advanced for VB coders"
Besides the insult that is to advanced VB developers everywhere, VB has always been a tool for developers who want the improved productivity provided by VB, and the more skilled among them have used other (COM/ActiveX) languages or hooked into Win32 to get things done that are not natively available. So VB has always catered for 'entry level' and advanced users.
So I'm puzzled by this argument that this proposal is too sophisticated for VB, because it may spook inexperienced or 'Typical VB' coders.
If that's your view of VB, then what's the point of this forum? One could argue that VB already has all the features the 'typical' or 'inexperienced' coder, and if that was the target market for VB.Net, then the job is complete, except for bug fixing and performance improvements.
But that's at best a naive view of the language, because you believe that VB is an 'entry level language', and that VB coders are by definition less skilled than, say, C# coders. At worst it's a malicious view of the language because you have some agenda to advance that involves the demise of future development of the language.
@KlausLoeffelmann I don't think this feature is too complicated for most of the VB programmers to understand. We already have many features that depend on custom attributes. Such as extension methods, hide module name, PInvoke, COM interface import/export and thread fields. If this feature accompany with nice intellisense behaviors for build-in auto-implemented property handler attributes, they will get used to it swiftly. For example, if user type the following code:
<Notify>
Public Property Count As Integer
And press enter, or press the > key at the following position:
<Notify Press ">" key here
Public Property Count As Integer
If NotifyOnPropertySet
is not exist nether in this class nor in base classes, the following code will be inserted automatically:
#Region "Auto-implemented property handlers"
' Visual Basic will handle auto-implemented properties' Set part with this Function if they have NotifyAttribute.
' Usage:
' <Notify>
' Public Property <PropertyName> As <PropertyType>
' For more information, please visit (doc link).
'''<Summary>
''' Raise PropertyChanged event when the property is being set to a different value.
''' </summary>
Protected Function NotifyOnPropertySet(Of T)(propertyName As String, ByRef backingField As T, value As T) As Boolean
If Object.Equals(value, backingField) Then Return True
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
End Function
#End Region
Whoa, didn't see this conversation had heated up (was too busy packing).
I think we're all mostly in what the language design meeting calls "violent agreement"; it looks like we disagree more than we actually do. @KlausLoeffelmann this is exactly as you describe it--infrastructure. I've describe a mechanism that could be implemented in the compiler to make it a little more productive to do certain kinds of things. I've also fleshed out the first draft of that design by trying to build a dozen example things. But that thing that would be "shipped" or advertised in a future version of VB would be those things. This mechanism would be a footnote, declarative MVVM would be the headline. In the way that My.Forms
and My.Settings
is the headline in VB2005 but the MyCollection
extensibility stuff is some infrastructure stuff that goes in the spec. Maybe at the bottom of some list on docs.microsoft.com for the curious. I also agree that the NotifyAttribute
and a base-class implementing the interface, declaring the event, and overridable methods for the property handler and OnPropertyChanged
method in particular should go into the Microsoft.VisualBasic
namespace or some other namespace imported by default for new VB projects. I repeat: NO declaring of attributes, or base classes, or events should be required for first-time programmers.
Yes, many intermediate or advanced VB developers will eschew the pre-canned base class for their own base class but... so what. The goal is for first-time developer to be crazy productive out of the box.
Adding a new ViewModel to a VB project should be as straight-forward as adding a new Form.
So for just that top echelon of VB developers. The P/Invokers and compiler extenders and framework authors, I ask:
@bandleader
It can't really be worked around with the CLR team. To the CLR there are no "events" really. There are just (usually) public methods named add_X
and remove_X
. It just so happens that the compiler generates a private field of delegate type and it generates those methods with code to mutate that field (and for VB only a private raise_X
method). But there's no guarantee that field exists or that those methods do anything or any way for any compiler in any language to know that that private field exists or how to access it in order to raise it. That's why implementers have always had to manually declare protected OnX
methods to raise it even in derived types. And there's definitely nothing in the interface of INotifyPropertyChanged
to let a piece of code in one assembly just raise any class's PropertyChanged
event and we could never add it because that would be a breaking change. It's really quite intractable :(
Please consider also a Constructed Attribute as I proposed here: https://github.com/dotnet/roslyn/issues/38367
@VBAndCs I like your Constructed Attribute proposal and responded, but could you explain its connection with this proposal of Anthony's?
@bandleader Both uses attributes to modify the property. In fact I replied here as a failsafe, in case of Roslyn team says it is a language related feature, or are not interested to add it to C# as well so it can be a VB feature only. If VB will upgrade property definition, so this is the place to refer to my proposal to be considered. Thanks.
Four months ago (November, 2017), Visual Basic MVP Klaus Löffelmann (@KlausLoeffelmann) was invited to attend the VB LDM to present on the challenges of modern GUI programming. Klaus presented a few different patterns and important concerns from the field. Expectedly, the tedium of implementing
INotifyPropertyChanged
was chief among them. This left the LDM with a renewed interest in addressing this scenario.Klaus did a prototype he called
UserInterface
properties that used an attribute<UserInterface>
to generateINotifyPropertyChanged
implementations.I proposed a slightly more general approach called
WithPropertyEvents
(temporary keyword choice).Klaus convinced me it was too messy, I adapted his prototype into a proposal specifically targeting
INotifyPropertyChanged
called Bindable Classes and Properties that was what Klaus designed but with a keyword instead of an attribute.Klaus updated his prototype to use a keyword instead of an attribute but chose a different keyword.
The VB LDM revisited the iced proposal for compiler plug-in source generators and/or metaprogramming via Replacable Members for address this scenario.
The VB looked at the three proposals on the spectrum from most general and expensive (meta-programming/generators) to most specific, self-descriptive, and cheapest (
Bindable
/UserInterface
) and felt that meta-programming was too far out and too uncertain to block other ideas and that neither of the alternatives would dissuade the pursuit of meta-programming in the future. The middle optionWithPropertyEvents
was selected to move forward as it was cheap/fast and still not hard-coded to a particular UI pattern to bake into the compiler.Lots of comments were left on the proposal regarding possible keyword choices.
I started working on a prototype of
WithPropertyEvents
with a working title/keyword choice ofTemplate
properties, as it changed the code-gen of auto-props to resemble an implementation of the classic OOP Template Method Pattern.I consulted with various friends and former colleagues for feedback. This design simplified based on feedback from them and from exploring implementation approaches which reduced the complexity of the code-gen from a property set having multiple pluging points via well-named methods to a vastly simplified single method passing arguments ByRef.
More contention about keyword choice:
Template
doesn't mean much, which is both not very meaningful, yet marketable--like Services and Workspaces".Callback
properties".I had several concerns about keyword choice:
Template:Binding
is going to get old. A keyword and an identifier gives too much visual space to the meaningless keyword.Joinpoint
,Pointcut
, andAdvice
.Callback Properties
orAdvice Properties
.Template Properties
sounds more marketable (though still vague).Alex (and others throughout history have proposed an attribute). I don't like the idea of an attribute for a baked-in pattern, but for an open-ended mechanism it seems good. The problem is the attribute isn't in the same class as the property and can't raise any events in another object.
Today
I ended up abandoning the whole
Template
property design entirely in favor of an extensible attribute based model I've tentatively titled "Property Handler Attributes". It's pretty simple. Given the existence of a well-known abstract attribute type, e.g.PropertyHandlerAttribute
, if one or more attributes derived from said well-known type is applied to an auto-prop the code-gen for the setter (and potentially getter) of that auto-prop will:NotifyAttribute
->NotifyOnPropertySet
).Shared
methodOnPropertySet
is looked up on the attribute class itself. If found, the compiler will perform overload resolution passing theMe
parameter of the property (or null if the property isShared
, the name of the property, a reference to the backing field, and the value parameter, and invoke the method. This allows simpler handlers which don't depend on special access (like raising an event) or state and whose logic would be the same for any property on any class, e.g.ThrowIfNullAttribute
.Boolean
and the result of the invocation is true, the setter will return immediately, ignoring subsequent handlers AND the setting of the backing field. This allows for a handler which prevents mutation (FreezableAttribute
) or ignores duplicate sets (common inINotifyPropertyChanged
implementations).<MaxLength(25)>
.This latest iteration addresses the original scenario, is general, has a marketable semi-descriptive name imho, dodges the keyword naming debate, doesn't significantly complicate the compiler and potentially simplifies a lot of programs. It takes repetitive situations that force you to give up the declarative benefits of auto-props to write boilerplate setters and allows you to keep it declarative, which I believe is more in keeping with the spirit of the language.
I implemented the prototype, played with it, good stuff. Now I want to share and get feedback. Here's some screenshots that illustrate the value (I'll build a shareable prototype when I get to a real computer. I've implemented this on a wholly inadequate laptop that's painful to code on):
Here are the property declarations involved:
Here's what some instance handlers themselves look like:![image](https://user-images.githubusercontent.com/10539978/37393310-fbd78734-272d-11e8-8dcc-5d20207e342b.png)
Here're some shared handlers (implementations in attributes themselves):![image](https://user-images.githubusercontent.com/10539978/37393435-50cc2416-272e-11e8-8363-c40c8940baf1.png)
Here's a doc comment helping a reader understand what an attribute does:![image](https://user-images.githubusercontent.com/10539978/37393465-67a4823c-272e-11e8-8fea-c111b5bdce5f.png)
Here's an example of the program running, showing off one of the validator attributes:![image](https://user-images.githubusercontent.com/10539978/37393541-9a5ebde6-272e-11e8-9085-e99ec9d88a0c.png)
The rest of the attributes I need to record interaction for you to see them work but...
Here's the generated IL for one of the setters:
And here's all the actual code for the various demos. Obviously most of this wouldn't ever appear in user-code: Models
UI Code-Behind
And here's my prototype branch.
Now I'm off to the Baltimore airport for another riveting day of flying across the country. Feedback welcomed!
-ADG