[C# feature] Auto-property syntax for custom setter/getter logic.

文章推薦指數: 80 %
投票人數:10人

Problem: having to declare a backing field when adding custom logic to getter and/or setter of a property. Current situation: private string ... Skiptocontent {{message}} dotnet / roslyn Public Notifications Fork 3.6k Star 15.7k Code Issues 5k+ Pullrequests 395 Discussions Projects 44 Security Insights More Code Issues Pullrequests Discussions Projects Security Insights Newissue Haveaquestionaboutthisproject?SignupforafreeGitHubaccounttoopenanissueandcontactitsmaintainersandthecommunity. Pickausername EmailAddress Password SignupforGitHub Byclicking“SignupforGitHub”,youagreetoourtermsofserviceand privacystatement.We’lloccasionallysendyouaccountrelatedemails. AlreadyonGitHub? Signin toyouraccount Jumptobottom [C#feature]Auto-propertysyntaxforcustomsetter/getterlogic. #1551 Closed dsafopenedthisissue Mar24,2015 ·16comments Closed [C#feature]Auto-propertysyntaxforcustomsetter/getterlogic. #1551 dsafopenedthisissue Mar24,2015 ·16comments Labels Area-LanguageDesign Discussion FeatureRequest Comments Copylink dsaf commented Mar24,2015 Problem:havingtodeclareabackingfieldwhenaddingcustomlogictogetterand/orsetterofaproperty. Currentsituation: privatestring_name;//Onlyusedbyproperty. publicstringName { get { Prepare(_name); return_name; } set { PreProcess(value); _name=value; PostProcess(value);//...orshouldwepass_name?Ambiguityfordevelopers. } } Suggestedchange: publicstringName { get { Prepare(value); returnvalue; } set { PreProcess(value); applyvalue; PostProcess(value); } } TypicalWPFscenarioafterchange: publicstringName { get; set { applyvalue; OnPropertyChanged();//Uses[CallerMemberName]orsomething,haven'ttriedit. } } Crazylambdaversion(separateissue?): publicstringName{get;setOnPropertyChanged;}//Setlambda(reducedtomethodgrouphere)isalwaysexecutedlastandisalwayspassedthevalue(isbasicallyanAction). Questions/comments: Isthisworthit,generally?Simplernon-AOPWPF/XAMLViewModel-s?Anyothercommonscenarios? Isaddinganewkeyword'apply'(oppositeof'return')worthit? Doesthesuggestedchangelookgoodenoughwhenusedtogetherwithauto-propertyinitializers? Maybewesimplyneedtokeepfieldsclosetopropertiesonsyntaxlevel? publicstring_nameName {...} Otherideasinolderdiscussion:https://roslyn.codeplex.com/discussions/550266 Thetextwasupdatedsuccessfully,buttheseerrorswereencountered: 👍 2 theoy added FeatureRequest Area-LanguageDesign labels Mar25,2015 Copylink KalitaAlexey commented Mar25,2015 Ithink#850isbetter Sorry,somethingwentwrong. Copylink Author dsaf commented Mar25,2015 @KalitaAlexeyIdisagree: Theissueseemstoberegardingspecificallynon-autoproperties,especiallygiventhecommentslike"Idisagreeaddinganewkeyword,firstitwilllimitonepropertyhasonlyonefield". Syntaxoptionsdiscussedtherearequitestrangeandsoundlikecreatingmini-classesoutofproperties,e.g."MyProperty.initialValue=;".What'snext-addingproperty-scopedmethodsandnestedtypes? It'sverysubjectivebutformethe'field'keywordisfocusingonmanagingthefield,while'apply'isfocusingonassigningthevaluetoproperty,whichismorepreferablewhenreasoningaboutauto-properties. Sorry,somethingwentwrong. dsaf mentionedthisissue Mar25,2015 Proposal:Property-scopedfields #850 Closed dsaf changedthetitle [C#feature][Discussion]Auto-propertysyntaxforcustomsetter/getterlogic. [C#feature]Auto-propertysyntaxforcustomsetter/getterlogic. Mar25,2015 Copylink KalitaAlexey commented Mar25,2015 @dsaf Ifyouwanttouseseveralfieldsinpropertygettersandsetters,thenwriteitexplicit publicstringFullName { get { returnlastName+""+firstName; } } IthinksyntaxwhichIsuggestedisstraightandnotconfusing Sorry,somethingwentwrong. Copylink Author dsaf commented Mar25,2015 @KalitaAlexeyOuropinionsaregettingsubjectiveatthisstage.Iguessit'suptoRoslynteamnowtodecide.Theimportantthingisthatwehavepointedoutaproblemandproposedseveraldifferentsolutions. Sorry,somethingwentwrong. Copylink KalitaAlexey commented Mar25,2015 @dsafIt'stoohardtodecide,becausetherearemanysolutions. Oneofthem: publicstringName { get; beforeset { if(field==value) returnfalse; } set; afterset { RaisePropertyChanged(nameof(Name)); } } Butproblemofadditionnewkeywordsalsoishard Sorry,somethingwentwrong. Copylink Author dsaf commented Mar25,2015 @KalitaAlexeybythewaythereisnoneedtopass"nameof(Name)"anymore: http://grenangen.se/node/75 https://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.callermembernameattribute%28v=vs.110%29.aspx Sorry,somethingwentwrong. Copylink bondsbw commented Mar25,2015 @dsafJusttobefair,someofthesyntaxissuesyoudescribeabout#850relatetothecommentsbutnottotheactualproposal.Also,thatproposal'sfocusisonencapsulatingthebackingfield,whichisnotexplicitlythegoalofyourissue. Thatsaid,Iappreciatewhatyouareproposing.Ifeelitisanorthogonalconcern,addingsimplebehaviorstoautomaticpropertyaccessors. TwothingsI'mnotclearon: Howwouldyour"Crazylambdaversion"syntaxdistinguishbetweenPrepare,PreProcess,andPostProcessitems? IsthereanywayforPreProcesstopreventthesetfromoccurring?Forexample,onlyallowingavaluetobesetonce: publicTelephonePhone { get{return_phone;} set { if(_phone==null) { _phone=value; } } } Sorry,somethingwentwrong. Copylink Author dsaf commented Mar25,2015 @bondsbwThatwouldbemorefair,agreed.Thereisanelementoforthogonality,true.Notbeing"forced"tokeepbackingfields"close"topropertiesissomethingthatbothersmeaswell-evenfromthesimplecodeformattingpointofview(tokeepallfieldsatthetopofthetypeornot?). "Crazylambdaversion"wouldonlyallowaPostProcessitem.Thisisverycontroversial,Iknow.Someonewouldneedtoassessthemosttypicalusecases,tosayifit'sareasonablesimplification.IwascomingfromtheINotifyPropertyChangedscenario. TheonlywayIcouldthinkofisdemandingthat'applyvalue'beasimplestatementthathastobepresentsomewhereonthe"firstlevel"ofthesettersbody(similartohowreturningavalueisenforcedforgetters).Anythingmorecomplicatedandusingabackingfieldstartstosoundmorereasonable. Sorry,somethingwentwrong. Copylink momijin commented Mar25,2015 @dsaf@KalitaAlexey Ialsowriteoneofthem: publicTPropertyName { get(Funcprepare); set(FuncpreProcess,ActionpostProcess); } Asetaccessorisalsoabletotakenasfollows: set(FuncpreProcess); set(ActionpostProcess); example: publicstringName { get(currentValue=>currentValue??newstring()); set((oldValue,newValue)=>oldValue!=newValue,(oldValue,newValue)=>OnPropertyChanged()); } Aboveisexpandedtobycompiler: privatestring_name; publicstringName { get { Funcprepare=currentValue=>currentValue??newstring(); _name=prepare(_name); return_name; } set { FuncpreProcess=(oldValue,newValue)=>oldValue!=newValue; ActionpostProcess=(oldValue,newValue)=>OnPropertyChanged(); if(preProcess(_name,value)) { stringoldValue=_name; _name=value; postProcess(oldValue,_name); } } } @bondsbw IthinkthatProperty-scopedfields#850isaveryniceidea,whichmakesitwherefieldsshouldbe.InsimplecaseIuseAuto-propertysyntax.Butwhenitisn'tso,IwilluseProperty-scopedfields.IwishthatC#7willsupportit. Sorry,somethingwentwrong. Copylink yume-chan commented Mar25,2015 Theapplykeyword:I'musingauto-propertysowhyIstillneedtosetbackingfieldbymyself? Iprefer@KalitaAlexey'swaysoget;set;stillindicatesit'sanauto-propertyandbefore/afterget/set;canaddcustomlogictoit. setOnPropertyChanged;:Ithinkifitwillbeaddedtostandard,itshouldprovideacustommethodtotakecontrolallthesettingprocess,inanotherwordsit'sjustashort-handforset{SetValue(value,nameof(Property));}(Andget{returnGetValue(nameof(Property));})(Soit'snotanauto-property)andit'seasiertounderstand.(Mentionedintheolddiscussion,butIthinkusespaceisbetter). @dsafsaid: Syntaxoptionsdiscussedtherearequitestrangeandsoundlikecreatingmini-classesoutofproperties,e.g."MyProperty.initialValue=;".What'snext-addingproperty-scopedmethodsandnestedtypes? Ithinkit'slikeJavaScript,everythingisanobjectsotheycanhavetheirownfields,Itaddsmorerelevancebetweenthepropertyandfieldsaffectsit.AndinC#werestrictonlypropertiescanhavefieldsoitwon'tcausemoremassbecausewealreadyhaveclasses. Differencefrom#850:Wehavecustompropertyandauto-property,sowehavethisissueand#850,fromdifferentstartingpoint. Problems Ifusingbeforeset;,canIeditfield(thekeywordreferencescompilergeneratedbackingfield)orvaluetosetfullycustomvalue?ORwhenusingapplykeyword,canIapplyacustomvalue? Ifwecanfullycontrolthelogic,Maybesomeonewillcreateacustompropertywithautogeneratedbackingfield,isitokorisitwewanted?(Itmightbemostimportant). WhenusingsetSomeMethod;(mentionedabove,notfirstpostver,SomeMethodwillsetvalueusingsomeotherway),whatargumentsshouldbepassedintothemethod? Sorry,somethingwentwrong. Copylink KalitaAlexey commented Mar26,2015 Ithinkno.Imean"beforeset"musthaveonepurpose-checkavailabilityofpropertyassignment. Iamnotsurehowhardtoimplementthis,butIwouldpreferthis"Ifbackingfieldisusedingetterorinsetter,thengeneratebackingfield.".AndIamnotsurebutIthinkbackingfieldmustbeusedingetterandinsetter.Ihavenoexampleofusingbackingfieldonlyinoneofthem. Ilookedatexample@momijinandIstillthinkwaywith"before/afterset"isbetter.Causelambdasyntaxcannotbedebugged.Icanplaceabreakpointinsideget.Inlambdaversionitisimpossible classPerson { publicstringName { get { returnfield??(field=newstring()); } beforeset { if(field==value) break; } set; afterset { OnPropertyChanged(); } } } AlsoIthinkwillbecoolIfI'llcanwritesomethinglikethis,butIunderstanditveryhardtoimplementandalsoitisnewkeywords,butthisisreallyusefulandsimpletowriteandunderstand. classPerson { publicstringName { get { returnfield??(field=newstring()); } beforesetchecknotequal; set; aftersetnotify; } } Sorry,somethingwentwrong. Copylink jbjoshi commented Mar27,2015 Howaboutfollowingsyntax: //Standardproperty publicstringDefaultProperty{get;set;}usingDefaultPropertyProvider; //Not-nullableproperty publicstringNotNullableProperty{get;set;}usingNotNullablePropertyProvider; //INPCproperty publicstringInpcProperty{get;set;}usingInpcPropertyProvider; Followingisaveryroughversionof'wouldbeimplementation': Systemclasses: //Propertyinformationrelatedtocurrentproperty publicstructPropertyProviderContext{ //Objectoftypethatthepropertybelongsto publicobjectTarget; //Nameofcurrentproperty publicstringPropertyName; //Existingvalueofcurrentproperty publicTPropertyValue; } //Atypethjatisusedto'mutate'propertycodegeneration publicinterfaceIPropertyProvider { //takesthecontext,returnsavalueorthrowsexception TGetValue(PropertyProviderContextcontext); //takesthecontextandnewvalue,returnsavaluethatshouldactuallybesetinproperty TSetValue(PropertyProviderContextcontext,TnewValue); } Implementations: //Standardimplementation publicclassDefaultPropertyProvider:IPropertyProvider { publicTGetValue(PropertyProviderContextcontext) { returncontext.PropertyValue; } publicTSetValue(PropertyProviderContextcontext,TnewValue) { returnnewValue; } } //Preventnullvalues publicclassNotNullablePropertyProvider:IPropertyProviderwhereT:class { //Ifexistingvalueisnull,throwexception publicTGetValue(PropertyProviderContextcontext) { if(context.PropertyValue==null) { thrownewInvalidOperationException(); } returncontext.PropertyValue; } //Ifgivenvalueisnull,throwexception publicTSetValue(PropertyProviderContextcontext,TnewValue) { if(newValue==null) { thrownewArgumentNullException(); } returnnewValue; } } //Acontractthatallowsothertypestoinvokepropertychangedeventforthistype publicinterfaceISupportsInpcInvocation { voidRaisePropertyChanged(stringpropertyName); } //ApropertyproviderthatsupportsINotifyPropertyChangedbehavior publicclassInpcPropertyProvider:IPropertyProviderwhereT:class { //Nothingspecial publicTGetValue(PropertyProviderContextcontext) { returncontext.PropertyValue; } //Raisepropertychangedsignalifvaluesdiffer publicTSetValue(PropertyProviderContextcontext,TnewValue) { if(context.PropertyValue!=newValue) { (context.TargetasISupportsInpcInvocation).RaisePropertyChanged(context.PropertyName); } returnnewValue; } } Somethingmorerefinedversionofthisapproachshouldhelpcompilerwhatcodetogenerateforeachproperty. Thoughts? Sorry,somethingwentwrong. Copylink Author dsaf commented Mar27,2015 @jbjoshidon'tbeoffended,butIMHOitlookslikesomethingfromWPForJava(thinkBooleanToVisibilityConverterandAbstractSingletonProxyFactoryBean)-Rubyguyscallthis"ceremony".Iwouldratheruseabackingfield. Sorry,somethingwentwrong. Copylink jbjoshi commented Mar27,2015 @dsaf,notatall. IAMinfluencedalotbyWPF. Iwouldratherhavethesekindsof'extensions'for'compiler'touseinsteadofthecompilerdecidingonit'sownonwhatcodetogenerate. Similarto'typeproviders'conceptinF#,compilerusesourclassestomakedecisions. EDIT: Bytheway,thereisnothinginherethat'assemblyrewriter'cannotdo.It'sjustabouthavinglanguagefeaturesextensibleoutofthebox.MorelikeAOPoutofthebox. Sorry,somethingwentwrong. Copylink momijin commented Mar27,2015 @CnSimonChan 4.Differencefrom#850:Wehavecustompropertyandauto-property,sowehavethisissueand#850,fromdifferentstartingpoint. Iagreetothat,too.Inthisissue,1)applykeyword,2)before/aftersetandfieldkeyword,3)lambdainget/setareappeared.Thosemademeexcitedandthesuggestionof@CnSimonChanand@KalitaAlexeyareveryinterestingtome.Ithinkthatthisissueshouldbeusefulforfuture. Sorry,somethingwentwrong. gafter added the Discussion label Nov20,2015 bondsbw mentionedthisissue Feb17,2017 Proposal:Property-ScopedFields dotnet/csharplang#133 Open Copylink Contributor gafter commented Mar20,2017 Wearenowtakinglanguagefeaturediscussiononhttps://github.com/dotnet/csharplangforC#specificissues,https://github.com/dotnet/vblangforVB-specificfeatures,andhttps://github.com/dotnet/csharplangforfeaturesthataffectbothlanguages. Sorry,somethingwentwrong. gafter closedthis Mar20,2017 Signupforfree tojointhisconversationonGitHub. Alreadyhaveanaccount? Signintocomment Assignees Nooneassigned Labels Area-LanguageDesign Discussion FeatureRequest Projects Noneyet Milestone Nomilestone Linkedpullrequests Successfullymergingapullrequestmayclosethisissue. Noneyet 8participants Youcan’tperformthatactionatthistime. Yousignedinwithanothertaborwindow.Reloadtorefreshyoursession. Yousignedoutinanothertaborwindow.Reloadtorefreshyoursession.



請為這篇文章評分?