9789463560412

Page 1

Inhoud

Inleidingxiii

Voorwieisditboekbedoeld?xiv

Overdeinhoudxiv

Codeconventiesxv

Feedbackgevenxvi

Dankwoordxvi

Overdeauteurxvii

1Werkenmetgegevenstypen1

Advies1:Gebruikeigenschappeninplaatsvantoegankelijkedatamembers2

Advies2:Kiesimplicieteeigenschappenbovenvariabeledata8

Advies3:Kiesvoorconstantevalue-typen12

Advies4:Onderscheidmakentussenvalue-typenenreference-typen19

Advies5:Zorgervoordat0eengeldigestatusvoorvalue-typenis24

Advies6:Zorgervoordatdeeigenschappenzichgedragenzoalsgegevens29

Advies7:Beperkhetbereikvaneentypemettuples34

Advies8:Definieerlokalefunctiesopanoniemetypen40

Advies9:Begrijpderelatiestussendeveleverschillendebegrippenvan gelijkheid

46

Advies10:BegrijpdevalkuilenvanGetHashCode()54

2API-ontwerp63

Advies11:VermijdconversieoperatoreninuwAPI’s64

Advies12:Gebruikoptioneleparametersomoverloadingvan methodenteminimaliseren68

Advies13:Beperkdezichtbaarheidvanuwtypen72

Advies14:Geefdevoorkeuraanhetdefiniërenenimplementeren vaninterfacesbovenovererving76

Advies15:Begrijphoeinterfacemethodenverschillenvanvirtuelemethoden84

Advies16:Implementeerheteventmodelvoormeldingen89

ix

Advies17:Vermijdhetretournerenvanverwijzingennaar interneklassenobjecten95

Advies18:Kiesoverschrijvingenboveneventhandlers99

Advies19:Overloadgeenmethodendiezijngedefinieerdinbasisklassen102

Advies20:Begrijphoeeventsmeerruntimekoppelingen

tussenobjectengenereren106

Advies21:Declareeralleennonvirtualevents109

Advies22:Maakmethodegroependieduidelijk,minimaalenvolledigzijn115

Advies23:Geefdeelklassendeelmethodenvoorconstructors,mutatorsen eventhandlers122

Advies24:VermijdICloneableomdathetuwontwerpkeuzenbeperkt127

Advies25:Beperkarrayparameterstotparams-arrays132

Advies26:Schakeldirectefoutrapportageinbijiteratorsen asyncmethodenmetbehulpvanlokalefuncties136

3Taakgerichtasynchroonprogrammeren143

Advies27:Gebruikasync-methodenvoorasynchroonwerk144

Advies28:Schrijfnooitasyncvoid-methoden148

Advies29:Vermijdhetsamenstellenvansynchroneen

asynchronemethoden154

Advies30:Gebruikasync-methodenomthreadtoewijzingenen contextwisselingentevermijden158

Advies31:Vermijdhetonnodigordenenvancontext160

Advies32:AsynchroonwerksamenstellenmetTask-objecten164

Advies33:Overweegdeimplementatievanhettaakannuleringsprotocol170

Advies34:Cachegegeneraliseerdeasyncreturntypen177

4Parallelleverwerking181

Advies35:LeerhoePLINQparallellealgoritmenimplementeert182

Advies36:Construeerparallellealgoritmenmetexceptions inhetachterhoofd194

Advies37:Gebruikdethreadpoolinplaatsvanthreadstemaken200

Advies38:GebruikBackgroundWorkervoorcross-threadcommunicatie206

Advies39:Cross-threadaanroepeninXAML-omgevingenbegrijpen209

Advies40:Gebruiklock()alsuweerstekeuzevoorsynchronisatie218

Advies41:Gebruikhetkleinstmogelijkebereikvoorvergrendelhandles225

Advies42:Vermijdhetaanroepenvanonbekendecodein vergrendeldesecties229

Inhoud x

5Dynamischprogrammeren235

Advies43:Begrijpdevoor-ennadelenvandynamischtyperen236

Advies44:Gebruikdynamischtyperenomteprofiterenvanhet runtimetypevangenerictypeparameters245

Advies45:GebruikDynamicObjectofIDynamicMetaObjectProvider voorgegevensgestuurdedynamischetypen248

Advies46:BegrijphoeudeExpressionAPIgebruikt259

Advies47:MinimaliseerdynamischeobjecteninpublicAPI‘s266

6DeelnemenaandeC#-community273

Advies48:Zoekhetbesteantwoord,niethetpopulairsteantwoord274

Advies49:Neemdeelaanspecsencode276

Advies50:Overweegomwerkwijzenmetanalysersteautomatiseren277

Index281

xi Handboek– EffectieverprogrammereninC#

Inleiding

DeevolutieenveranderingvanC#blijftdoorgaan.Endaarmeeverandertook deC#-community.VoormeerontwikkelaarsisC#deeersteprofessioneleprogrammeertaal.Deledenvanonzecommunitywordennietgehinderddoorde vooropgezetteideeëndiegebruikelijkzijnonderdegenendieC#zijngaan gebruikennajarenervaringmetandereopCgebaseerdetalen.ZelfsdeontwikkelaarsdieC#aljarengebruikenvoelendenoodzaakomzichnieuwewerkwijzeneigentemakenalsgevolgvandesnelleopeenvolgingvanveranderingen.Sindsdecompileropensourceis,volgendeinnovatiesindeC#-taalelkaar snelop.DereviewvanvoorgesteldefunctionaliteitvoordeC#-taalgebeurtnu doordehelecommunityinplaatsvaneen kleinegroeptaalexperts.Decommunitykannuookdeelnemenaanhetontwerpenvandenieuwefunctionaliteit.

Wijzigingeninvoorgesteldearchitecturenentoepassingenveranderenookde taalidiomendiewijalsC#-ontwikkelaarsgebruiken.Hetbouwenvantoepassingendoorhetschrijvenvanmicroservices,distributedprogramma’sendescheidingvandataenalgoritmesmakenallemaaldeeluitvanmodernesoftwareontwikkeling.DeC#-taalheeftdeeerstestappengezetvoordeopnamevan dezeverschillendeidiomen.

Deorganisatievanhet HandboekeffectieverprogrammereninC# weerspiegelt zoweldewijzigingenindetaalalsdewijzigingenindeC#-community.Ditboek neemtunietmeeopeenhistorischereisdoordeveranderingenindetaal, maarbiedtuadviesoverhetgebruikvandehuidigeC#-taal.Deverschillende adviezenbehandelendenieuwetaal-enstructuureigenschappenendepraktijkendiedecommunityzichheefteigengemaaktdoorhetbouwenvanverschillendeversiesvansoftwareproductenmetC#.Dezevijftigadviezenvormeneen verzamelingaanbevelingendieualsprofessioneelontwikkelaarkuntgebruiken omC#meereffectiefintezetten.

DitboekgaatervanuitdatuC#7gebruikt,maarhetisgeenuitputtende behandelingvandenieuwetaalfuncties.Ditboekbiedtpraktischadvieshoeu dezefunctieskuntgebruikenvoorhetoplossenvanproblemenwaaruinde dagelijksepraktijktegenaankuntlopen.HetbehandeltinhetbijzonderdieC# 7-functionaliteitwaarmeeuopeennieuweenbeteremanierveelgebruikt idioomkuntschrijven.EenInternetzoekactietoontnogsteedsdeoplossingen diealjarenmeegaan.Ditboekbelichtdezeoudereoplossingenenlegtuit waaromdenieuwefunctionaliteitinC#betereoplossingenmogelijkmaakt.

VeelvandeaanbevelingeninditboekkuntucontrolerenmetopRoslyn-gebaseerdeanalysersencodefixes.Ikonderhoudeenrepositoryvandezebronnen

xiii

opditadres: https://github.com/BillWagner/MoreEffectiveCSharpAnalyzers

Wanneeruideeënhebtofwiltbijdragenaandezerepository,schrijfdaneen bijdrageofstuurmeeenverzoek.

Voorwieisditboekbedoeld?

Het HandboekeffectieverprogrammereninC# isgeschrevenvoorprofessioneleontwikkelaarsvoorwieC#deprimaire programmeertaalis.Ikgaervanuit datubekendbentmetdesyntaxiseneigenschappenvanC#endatuvaardigheidhebtinhetschrijvenvancodeinC#.Ditboekbevatgeenuitlegover standaardinstructiesentaaleigenschappen.Inplaatsdaarvanwordtbesproken hoeudefunctionaliteitvandehuidigeversievandeC#-taalkuntintegrerenin uwdagelijkseontwikkelwerk.

Daarnaastgaatditboekervanuitdatuenigekennishebtvande Common LanguageRuntime (CLR)ende just-in-time (JIT)compiler.

Overdeinhoud

Dataisalomtegenwoordigindehuidige wereld.Ineenobjectgeoriënteerde aanpakzijndataencodeonderdeelvaneentypemetdedaarbijbehorende bevoegdheden.Eenfunctioneleaanpakbehandeltmethodesalsdata.Eenservicegerichteaanpakscheidtdedatavandecodediededatabewerkt.DeevolutievanC#heeftervoorgezorgddatde taalfunctionaliteitbevatdiegemeenschappelijkisvooraldezeparadigma’s, hetgeencomplicatieskanopleverenbij uwontwerpkeuzes.Hoofdstuk1bespreektdezekeuzesenbiedteenleidraad bijhetkiezenvaneengeschikttaalidioomvoorverschillendetoepassingen.

ProgrammerenisinwezenhetontwerpvandeAPI.Hetbrengtuwverwachtingenoverhetgebruikvanuwcodeoveraandegebruikers.Hetspreektook boekdelenoveruwinzichtindebehoeftenenverwachtingenvanandereontwikkelaars.Inhoofdstuk2leertuhoeu hiervoorhetrijkepaletvanC#-taalfunctieshetbesteinzet.Uziethoeuluieevaluatiegebruikt,configureerbare interfacesmaaktenonduidelijkheidvoorkomttussendeverschillendetaalelementeninuwalgemeneinterfaces.

Taak-gebaseerdasynchroonprogrammerenlevertnieuweidiomenopvoorhet samenstellenvantoepassingenmetasynchronebouwstenen.Hetbeheersen vandezefunctionaliteitbetekentdatuAPI’skuntmakenvoorasynchrone takendieduidelijkweergevenwatdecodeuitvoert,endiemakkelijkzijnte gebruiken.Inhoofdstuk3leertuhoeu detaak-gebaseerdeasynchronetaalfunctionaliteitgebruiktvoorcodediewordtuitgevoerddoormeerdereservices endiedaarvoordiversebronnengebruikt.

Inleiding xiv

Hoofdstuk4neemteenspecifiekesubsetvanasynchroonprogrammerenonderdeloep: multithreadedparallelexecution.UziethoeumetPLINQdeverwerkingvancomplexealgoritmeseenvoudigerverdeeltovermeerderecores enmeerdereCPU’s.

Hoofdstuk5bespreekthetgebruikvanC# alseendynamische taal.InC#speelt hettypeeengroterol,metnamestatischetypen.Tegenwoordigbevateen toenemendaantalprogramma’szoweldynamischealsstatischetypen.MetC# kuntugebruikmakenvandynamische programmeertechniekenzonderde voordelenvanstatischetypenbinnenhetheleprogrammateverliezen.In hoofdstuk5leertuhoeudynamischefunctiesgebruiktenhoeuvoorkomtdat dynamischetypenhetheleprogrammabinnensluipen.

Hoofdstuk6sluitditboekafmetsuggestiesoverhoeukuntdeelnemenaande wereldwijdeC#-community.Erzijnveelmanierenwaaropukuntparticiperen enwaarmeeukunthelpenbijdeaanpassingvandeprogrammeertaaldieu dagelijksgebruikt.

Codeconventies

Hetweergevenvancodeineenboekbetekenthetsluitenvancompromissen watbetreftruimteenduidelijkheid.Ikhebgeprobeerdomdevoorbeeldente focussenophetspecifiekepuntdatdecodeillustreert.Vaakbetekentdathet weglatenvananderegedeeltenvaneenklasseofeenmethode.Somsbetekent ditookhetachterwegelatenvanerrorrecoverycodeomruimtetebesparen. Eenpublicmethodedientdeparametersenandereinvoertevalideren,maar ookdiecodewordthiermeestalweggelaten.Uitruimteoverwegingenisook devalidatievoorhetaanroepenvanmethodesen try/finally-constructies weggelaten,dezecontroleszijnvaakopgenomeniningewikkeldealgoritmen.

Ikveronderstelookdatdemeesteontwikkelaarsdetoepasselijkenamespace (naamruimte)kunnenvindenwanneereenvoorbeeldeenvandeveelgebruiktenamespacesgebruikt.Ukuntervanuitgaandatelkvoorbeeldimpliciet devolgende using-statementsbevat:

usingSystem; usingstaticSystem.Console; usingSystem.Collections.Generic; usingSystem.Linq; usingSystem.Text;

xv Handboek– EffectieverprogrammereninC#

Feedbackgeven

Ondanksmijnbesteinspanningen–envandemensendiedeteksthebben nagekeken–ishetmogelijkdaterfoutenzijngeslopenindetekstofvoorbeelden.Alsudenktdatueenfouthebtgevonden,neemdancontactmetmijop viae-mail bill@thebillwagner.com ofviaTwitter @billwagner.Erratavindtu op http://thebillwagner.com/Resources/MoreEffectiveCS.Veelvandeadviezeninditboekzijngeïnspireerddoore-mail-enTwitter-gesprekkenmet andereC#-ontwikkelaars.Hebtuvragenofopmerkingenoverdeaanbevelingeninditboek,neemdancontactopmetmij.Discussiesvanalgemeen belangvindtuterugopmijnblogop http://thebillwagner.com/blog.

Dankwoord

Erzijnveelmensenaanwieikdankverschuldigdbenvoorhunbijdrageaandit boek.Ikhebhetvoorrechtomaldenodigejarendeeluittemakenvaneen verbazingwekkendeC#-community.Iedereenopde C#Insidersmailinglijst (binnenofbuitenMicrosoft)heeftbijgedragenmetideeënenconversaties,waardoorditeenbeterboekisgeworden.

IkmoeteenpaarledenvandeC#-communitypersoonlijkbedankenvoorde hulpmetideeën,enmethetomzettenvanideeëninconcreteaanbevelingen. DegesprekkenmetJonSkeet,DustinCampbell,KevinPilch,JaredParsons, ScottAllenenvooralMadsTorgersenzijndebasisvoorveelnieuweideeënin dezeuitgave.

Voordezeuitgavehadikdebeschikking overeengeweldigteamvantechnischerecensenten.JasonBock,MarkMichaelisenEricLippertbestudeerdende tekstenvoorbeeldenenverbeterdenzeerdekwaliteitvanhetboekdatunuin handenhebt.Hunrecensieswarengrondigencompleet,enmeerdandatkan niemandvragen.Daarnaastkwamenzemetaanbevelingendiemehielpenom veelvandeonderwerpenbeteruitteleggen.

HetteamvanAddison-Wesleyiseendroomommeetewerken.Trina MacDonaldiseenfantastischeredacteur,leermeesterendedrijvendekracht diehetwerkgedaankrijgt.ZesteuntopMarkRenfrowenOliviaBasegio,net alsik.Hunbijdragengarandeerdendat hetvoltooidemanuscripteenkwalitatiefhoogstandjewas,vancovertotcoverenallesdaartussenin.CurtJohnson blijftopmarketingtechnischgebiedfantastischwerkleveren.Hetmaaktniet uitwelkmediumuhebtgekozen,Curtheeftdehandgehadinhetbestaanvan ditboek.

IkvindheteeneeromdeeluittemakenvanScottMeyers’sserieboeken.Hij bekijktelkmanuscriptenbiedtsuggestiesenopmerkingenvoorverbetering. Scottisongelooflijkgrondigenzijnervaringinsoftware,hoewelnietinC#,

Inleiding xvi

betekentdathijallegebiedenvindtwaarikietsnietduidelijkgenoeghebuitgelegdofwaareenadviesgoedopzijn plaatszouzijn.Zijnfeedback,zoals altijd,isvanonschatbarewaardegeweestindevoorbereidingvandezeuitgave.

Zoalsaltijdheeftmijnfamiliemijdetijdgegevenzodatikditmanuscriptkon voltooien.MijnvrouwMarlenewachtte geduldigtallozeuren,terwijlikweggingomteschrijvenofvoorbeeldentemaken.Zonderhaarsteunzouikdit boeknooithebbenafgekregen,enhetzouooknietzobevredigendzijn geweestomdezeprojectentevoltooien.

Overdeauteur

BillWagner iseenvan’swereldsbelangrijksteC#-ontwikkelaarsenhijislid vandeECMAC#StandardsCommittee.HijisvoorzittervandeHumanitarian Toolbox,isbenoemdtotMicrosoftRegionalDirectoreniselfjaar.NETMVP,en hijtradonlangstoetotde.NETFoundationAdvisoryCouncil.Billheeft samengewerktmetbedrijven,variërendvanstarterstotgroteondernemingen, aanhetverbeterenvanhunsoftwareontwikkelingsprocesenhetuitbreiden vanhunsoftwareontwikkelingsteams.HijwerktmomenteelmetMicrosoftaan het.NETCorecontentteam.Hijcreëertleermiddelenvoorontwikkelaarsdie geïnteresseerdzijnindeC#-taalen.NETCore.BillbehaaldeeenBSinComputerScienceaandeUniversiteitvanIllinoisinChampaign-Urbana.

xvii Handboek– EffectieverprogrammereninC#

Werkenmet gegevenstypen

C#werdoorspronkelijkontworpenvoorsoftwareontwikkelingmetobjectgeoriënteerdetechnieken,waarindegegevensendefunctionaliteitwordensamengebracht.Naverloopvantijdzijnernieuweidiomentoegevoegdterondersteuning vansteedsvakervoorkomendeprogrammeertechnieken.Eenvan dietrendsishetscheidenvandegegevensopslagvandemethodendiedezegegevensbewerken.Dezetendenswordtgedreven doordeovergangnaargedistribueerdesystemen,waarineen applicatiewordtverdeeldinkleinereprocessen,dieelkéénfunctieofenkeleverwantefunctiesuitvoeren.Deintroductievaneen nieuwestrategievoorhetscheidenvangegevensenmethode resulteertnatuurlijkookindeontwikkelingvannieuweprogrammeertechnieken.Enzoleidennieuweprogrammeertechnieken weertotnieuwetaalfuncties.

Indithoofdstukleertutechniekenomdatatescheidenvande methodendiedezegegevensmanipulerenofverwerken.Deze gegevenszijnnietaltijdobjecten;somszijnhetfunctiesenpassievedatacontainers.

1

Advies1:Gebruikeigenschappeninplaatsvan

toegankelijkedatamembers

Eigenschappen(properties)zijnaltijdeenonderdeelgeweestvandeC#-taal, maarsindsdeeerstereleasevanC#zijnverschillendeuitbreidingengeïntroduceerdwaardoordeeigenschappennogkrachtigerzijn.Ukuntbijvoorbeeldverschillendetoegangsbeperkingenopgevenvoordegetterensetter.Gebruiktu Auto-Property,danhoeftuniethandmatigtypentedeclarerenvoordeeigenschappen(inplaatsvandatamembers)en kuntuautomatischaccessmodifiers toekennen,zoalsRead-Only.Expression-bodieddatamembersbiedeneennog beknopteresyntaxis.Alsunogsteedsveldenalspublicdeclareertbijuwdatatypen,stopdaardanmee.SchrijftunogsteedsGet-enSet-methodenmetde hand,houderdanmeeop.Meteigenschappenmaaktudatamemberseenvoudigbeschikbaaralsonderdeelvande publicinterface,terwijlutochdeverwachteinkapselingbehoudtvaneenobjectgeoriënteerdeomgeving.Eigenschappenzijntaalelementendietoegankelijkzijnalsofzedatamemberszijn, maarzewordengeïmplementeerdalsmethoden.

Sommigemembersvaneentypewordenhetbestweergegevenalsdata:de naamvaneenklant,de(x, y)-coördinatenvaneenpuntofdeomzetvanvorig jaar.Meteigenschappenkuntueeninterfacemakendiewerktalsofdeze rechtstreekstoegangheefttotdedatavelden,maardienogsteedsallevoordelenbiedtvaneenmethode.Clientcode benaderteigenschappenalsofdeze publicveldenbenadert.Defeitelijkeimplementatiegebruiktechtermethoden, waarinuhetgedragvandeeigenschappen-accessorsdefinieert.

Het.NETFrameworkgaatervanuitdatueigenschappengebruiktvooruw publicdatamembers.Sterkernog,deklassenvoorgegevensbindinginhet .NETFrameworkondersteuneneigenschappen,geenpublicdatafields.Dit geldtvoorallebibliothekenvoorgegevensbinding:WPF,WindowsFormsen WebForms.Gegevensbindingkoppelteeneigenschapvaneenobjectaaneen besturingselementvandegebruikersinterface.Hierbijwordt reflection gebruikt omdegenoemdeeigenschaptevindenineentype:

textBoxCity.DataBindings.Add(“Text”, address,nameof(City));

DezecodekoppeltdeeigenschapTextvanhetbesturingselementtextBoxCity aandeeigenschapCityvanhetobjectaddress.Ditwerktnietmeteenpublic datafieldmetdenaamCity;deontwerpersvandeFrameworkClassLibrary hebbenhiervoorgeenondersteuningingebouwd.Hetgebruikvanpublicdata memberswordtinobjectorientedprogramming(OOP)gezienalseenslechte

Hoofdstuk1 –Werkenmetgegevenstypen 2

publicclassCustomer {

werkwijze,zodatondersteuninghiervoornietisopgenomenindeFramework ClassLibrary.DezeomissieiseenredentemeeromdejuisteOOP-technieken tevolgen.

Gegevensbindingisalleenvantoepassingopklassenmetelementendiewordenweergegevendoordecodevanuwgebruikersinterface(UI).Maardat betekentnietdatueigenschappenuitsluitendmoetgebruikenindeUI-code: gebruikookeigenschappenvoorandereklassenenstructuren.Eigenschappen zijnveeleenvoudigertewijzigenwanneerulaterdeeisenofhetgedragwilt aanpassen.SteldatubesluitdathettypeKlantnooiteenlegenaammaghebben.AlsudeeigenschapvoorhetveldNaamalspublichebtingesteld,danis dezenieuweeiseenvoudigtoetevoegen,omdatditslechtsopéénplaats hoefttegebeuren:

privatestringname; publicstringName

get=>name; set

if(string.IsNullOrWhitespace(value)) thrownewArgumentException( “Namecannotbeblank”, nameof(Name)); name=value; }

//Moreelided } }

Haduhiervoorpublicdatamembersgebruikt,danhadudegehelecodemoetendoorlopenenaanpassenopiederelocatiewaardenaamvandeklant wordttoegewezen.Datkostmeertijd,veelmeertijd.

Omdateigenschappenwordengeïmplementeerdmetmethoden,ishettoevoegenvanondersteuningvoormultithreadingeenvoudiger.Ubreidtde implementatievandeget-enset-accessorsuitmetgesynchroniseerdetoegang totdedata(zieadvies39voormeerinformatie):

publicclassCustomer {

privateobjectsyncHandle=newobject();

{
{
3 Handboek– EffectieverprogrammereninC#

privatestringname;

publicstringName { get { lock(syncHandle) returnname; } set { if(string.IsNullOrEmpty(value)) thrownewArgumentException( “Namecannotbeblank”, nameof(Name)); lock(syncHandle) name=value; }

//Moreelided

publicclassCustomer

Eigenschappenhebbendezelfdetaalfunctiesalsmethoden.Eneigenschappen kunnenookvirtueelzijn:

publicvirtualstringName

get; set; }

Merkopdatdelaatstepaarvoorbeeldendeimplicieteeigenschapsyntaxis gebruiken.Hetisgebruikelijkommeteeneigenschapeenbackingstoreopte zetten.Meestalhoeftugeencodevoorvalideringtoetevoegenaandeaccessorsvandeeigenschap.DeC#-taalondersteuntdevereenvoudigdeimpliciete syntaxisvaneigenschappenzodatveelvandeceremoniëlecodeachterwege kanblijvenwaarmeeeeneenvoudigveldzichtbaarisalseigenschap.Decompilercreëerteenprivateveld(meestaleen backingstore genoemd)enimplementeertdebenodigdelogicavoorzoweldeget-alsdeset-accessor.

Ukunteigenschappenookalsabstractdefiniëreneneigenschappendefiniëren alsonderdeelvaneeninterfacedefinitie.Hiervoorgebruiktuvergelijkbaresyn-

}
}
{
{
}
Hoofdstuk1 –Werkenmetgegevenstypen 4

taxisalsbijimplicieteeigenschappen.Inhetvolgendevoorbeeldzietueen eigenschapsdefinitieineengeneriekeinterface.Hoeweldesyntaxisconsistent ismetimplicieteeigenschappen,bevatdezeinterfacedefinitiegeenenkele implementatie.Hetdefinieerteencontractwaaraanelktypemoetvoldoendat dezeinterfaceimplementeert.

publicinterfaceINameValuePair<T>

stringName{get;}

TValue{get;set;}

Eigenschappenzijnvolwaardige,eersteklastaalelementendieeenuitbreiding zijnvanmethodendieinternegegevensbenaderenofwijzigen.Alleswatu kuntdoenmetmember-functies,kuntudoenmeteigenschappen.Methet gebruikvaneigenschappenvermijdtuookeenanderebelangrijkebronvan foutendiemetveldenmogelijkis:ukuntgeeneigenschapaaneenmethode doorgevenmethetkeyword ref of out.

Deaccessorsvooreeneigenschapzijntweeverschillendemethodendiebinnenhettypezijngecompileerd.UkuntinC#bijeeneigenschapverschillende accessmodifiersopgevenvoordeget-enset-accessors.Dezeflexibiliteitgeeft unogmeercontroleoverdezichtbaarheidvandegegevenselementendieu meteigenschappeninstelt:

publicclassCustomer

publicvirtualstringName { get; protectedset; }

//Remainingimplementationomitted }

Desyntaxisvandeeigenschapreiktverderdaneenvoudigegegevensvelden. Alsuwtypegeïndexeerdeitemsbevatalsonderdeelvandeinterface,dankunt uindexeerdersgebruiken.Indexeerderszijnhiergeparametriseerdeeigenschappen.Dezewerkwijzeiseenhandigemanieromeeneigenschaptemaken diedeitemsineenreeksretourneert:

publicintthis[intindex]

{
}
{
{ 5 Handboek– EffectieverprogrammereninC#

get=>theValues[index]; set=>theValues[index]=value; }

privateint[]theValues=newint[100];

//Accessinganindexer: intval=someObject[i];

Indexeerdershebbendezelfdetaalondersteuningalsdeeigenschappenvan eenenkelitem:zewordengeïmplementeerdalsmethodendieuschrijft,zodat uelkeverificatieofberekeningbinnendeindexeerfunctiekunttoepassen.Een indexeerderkanvirtueelofabstractzijn,ukuntzedeclarerenininterfaces,en zekunnenread-onlyofread-writezijn.Eendimensionaleindexeerdersmet numeriekeparameterszijntoegankelijkvoorgegevensbinding.Andere indexeerdersmetniet-integereparameterskuntugebruikenomkaartente definiëren:

publicAddressthis[stringname]

{

get=>addressValues[name];

set=>addressValues[name]=value;

privateDictionary<string,Address>addressValues;

InovereenstemmingmetdemultidimensionalearraysinC#,kuntumultidimensionaleindexeerdersmakenmetovereenkomstigeofverschillende typenopelkeas:

publicintthis[intx,inty]

=>ComputeValue(x,y);

publicintthis[intx,stringname]

=>ComputeValue(x,name);

Merkopdatalleindexeerderszijngedeclareerdmethetkeyword this.Ukunt eenindexeerderinC#geennaamgeven,dusheeftelkeaparteindexeerderin eentypeeenduidelijkeparameterlijst nodigomonduidelijkheidtevoorkomen. Bijnaallemogelijkhedenvaneigenschappenzijnookbeschikbaarvoor indexeerders:indexeerderskunnenvirtueelofabstractzijn;zijkunnenafzonderlijkeaccessmodifiershebbenvoor settersengetters.Erisechteréénverschil:ukuntgeenimplicieteindexeerdersmaken,ietswatwelkanmeteigenschappen.

}
Hoofdstuk1 –Werkenmetgegevenstypen 6

Dezefunctionaliteitvaneigenschappenisprimaenhetiseenfijneverbetering tenopzichtevaneerdereversiesvanC#.Maarwellichtbentunogsteeds geneigdomeeneersteimplementatiemetdatamemberstemakenen–zodra udevoordelendaarvannodighebt–dedatamemberstevervangendoor eigenschappen.Datklinktalseenredelijkestrategie,maarhetisverkeerd.

Bekijkhetvolgendegedeelte vaneenklassendefinitie:

//Usingpublicdatamembers,badpractice: publicclassCustomer { publicstringName;

//Remainingimplementationomitted }

Dezeklassendefinitiebeschrijfteenklantmeteennaam.Ukuntdenaam opvragenofinstellenmetdegebruikelijkenotatie:

string name=customerOne.Name; customerOne.Name=“ThisCompany,Inc.”;

Datiseenvoudigenrechttoerechtaan.U kuntzichvoorstellendatulaterhet datamemberNamekuntkuntvervangendooreeneigenschap,endatdecode ongewijzigdzoublijvenwerken.Datisminofmeerwaar.Eigenschappenzijn bedoeldomopdatamemberstelijkenalszewordenbenaderd,datisimmers hetdoelvandesyntaxis.Maareigenschappenzijn geen gegevens;detoegang toteeneigenschapgenereertandereMSIL-instructies(MicrosoftIntermediate Language)dandetoegangtotgegevens.

Hoeweleigenschappenendatamemberscompatibelzijnindebroncode,zijn zenietbinaircompatibel.Inhetvoor dehandliggendegevalbetekentdezebeperkingdatwanneeruvaneenpublicdatamemberoverschakeltnaardeequivalentepubliceigenschap,ualleco dediegebruikmaaktvanhetpublicdata member,opnieuwmoetcompileren.C#behandeltbinairesamenstellingenals eersteklasburgers.Eéndoelvandetaalisdathetmogelijkisoméénenkelebijgewerkteassemblagevrijtegevenzonderdevolledigetoepassingteupdaten. Hetveranderenvaneendatamemberineeneigenschapverbreektdebinaire compatibiliteit,endaarmeewordthetupgradenvaneenenkeleassemblage veelmoeilijker.

AlsudeMSIL-instructies vooreeneigenschapbekijkt,zouuzichkunnenafvragenwatderelatieveperformanceisvaneigenschappenendatamembers.De prestatiesmeteigenschappenzullennietsnellerzijndanmetdatamembers, maarwaarschijnlijkooknietlangzamer.De just-in-time(JIT)compilerverwerkt

7 Handboek– EffectieverprogrammereninC#

inlinebepaaldemethodeaanroepen,inclusiefdievanpropertyaccessors.Als deJIT-compilerinlinedepropertyaccessorsafhandelt,danzijndeprestaties vandatamemberseneigenschappenhetzelfde.Zelfswanneereenproperty accessornietinlinewordtafgehandeld,danishetverschilinprestatiesdeverwaarloosbaretijdvaneenfunctieaanroep.Ditverschilisalleenineenklein aantalsituatiesmeetbaar.

Eigenschappenzijnmethodendiezichtbaarzijnvanuitdeaanroependecode zoalsgegevens,ietswatwaarschijnlijkbijuwgebruikerseenaantalverwachtingenwekt.Zijziendetoegangtoteeneigenschapalsofhetdetoegangtot datais.Immers,zozietheteruit.Uwpropertyaccessorsmoetendezeverwachtingenwaarmaken.Get-accessorszoudengeenwaarneembarebijwerkingenmoetenhebben.Daarentegenwijzigenset-accessorsdestatus,en gebruikerszoudendezeveranderingenmoetenkunnenzien.

Propertyaccessorswekkendusookprestatieverwachtingenbijuwgebruikers. Eenpropertyaccesszieteruitalseendatafieldaccess.Erzoudengeensignificantandereprestatiekarakteristiekenmogenzijntenopzichtevaneeneenvoudigedataaccess.Propertyaccessorsdienengeenlangdurigeberekeningenuit tevoerenofaanroepentussenapplicatiestemaken(zoalshetuitvoerenvan databasequery’s)ofanderelangdurigebewerkingenuitvoerendienietconsistentzijnmetwatuwgebruikersverwachtenvaneenpropertyaccessor.

Gebruikeigenschappenwanneerugegevensbeschikbaarmaaktindepublicof protectedinterfacesvaneentype.Gebruikeenindexeerdervoorreeksenof dictionary’s.Declareeralledatamemberszonderuitzonderingalsprivate.Deze instellingenbiedenonmiddellijkondersteuningvoorgegevensbinding,waardooruindetoekomstveeleenvoudigerdeimplementatievandemethoden kuntaanpassen.Hetextrawerkdatnodigisomeenvariabeleineeneigenschapintekapselen,bedraagtéénoftweeminutenvanuwdag.Tervergelijking,wiltuachterafeigenschappengebruikenenervoorzorgendatuw programma’scorrectblijvenwerken,danbrengtdatveleurenwerkmetzich mee.Wanneerunueenbeetjetijdinvesteert,danbespaartuzichzelflater veeltijd.

Advies2:Kiesimplicieteeigenschappen bovenvariabeledata

UitbreidingenaandesyntaxisvaneigenschappeninC#latenuuwontwerpdoel meteigenschappenduidelijkmaken.DemoderneC#-syntaxismaakthetmogelijkdatuachterafookuwontwerpkuntwijzigen.Beginmeteigenschappenen maakveeltoekomstigescenario’smogelijk.

Hoofdstuk1 –Werkenmetgegevenstypen 8

Wanneerubenaderbaregegevensaaneenklassetoevoegt,zijndeeigenschapsaccessorsvaaksimpeleomslagen(wrappers)vooruwgegevensvelden. Alsdathetgevalis,danverhoogtudeleesbaarheidvanuwcodedoorimplicieteeigenschappentegebruiken:

publicstringName{get;set;}

Decompilermaakthetbackingfieldmeteendoordecompilergegenereerde naam.Metdesettervandeeigenschapkuntudewaardevanhetbackingfield wijzigen.Omdatdecompilerdenaamvanhetbackingfieldgenereert,moetu ookbinnendeeigenklassedeeigenschapsaccessoraanroepenomhetbacking fieldtewijzigen.Datisgeenprobleem:hetaanroepenvandeeigenschapsaccessordoethetwerk,enomdatdegegenereerdeeigenschapsaccessoreen enkeltoewijzingsstatementis,wordthetwaarschijnlijkinlineuitgevoerd.Het runtimegedragvandeimplicieteeigenschapishetzelfdealshetruntimegedrag bijhetbenaderenvanhetbackingfield,ookwatbetreftperformance.

Implicieteeigenschappenondersteunendezelfdeaccessmodifiersalshun explicietetegenhangers.Ukuntzelfde gewensterestrictiestoevoegenaande setaccessor:

publicstringName { get; protectedset; }

//Or publicstringName { get; internalset; }

//Or publicstringName { get; protectedinternalset; }

//Or publicstringName { get; privateset; }

9 Handboek– EffectieverprogrammereninC#

//Canbesetonlyintheconstructor: publicstringName{get;}

Implicieteeigenschappengenererendezelfdecodevooreeneigenschapmet backingfieldalsdieuzelfineeneerdereversievanC#handmatigzouhebben geschreven.Gebruiktuimplicieteeigenschappen,danwordtuproductieveren uwklassenzijnbeterleesbaar.Dedeclaratievaneenimplicieteeigenschap toontaaniedereendieuwcodeleestprecieswatuwiltmaken.Deextrainformatiekanachterwegeblijven,zodathetbestandoverzichtelijkblijft.

Aangezienimplicieteeigenschappendezelfdecodegenererenalsexpliciete eigenschappen,kuntuimplicieteeigenschappengebruikenomvirtueleeigenschappentedefiniëren,virtueleeigenschappenteoverschrijven(override)of eeneigenschapteimplementerendieisgedefinieerdineeninterface.

Wanneeruimplicieteenvirtueleeigenschapmaakt,hebbenafgeleideklassen geentoegangtotdedoordecompilergegenereerdebackingstore.Echter, overschrijvingen(overrides)hebbenweltoegangtotdeaccessmethodes get en set vandebasiseigenschappen,netals metelkeanderevirtuelemethode:

publicclassBaseType

publicvirtualstringName

get; protectedset;

publicclassDerivedType:BaseType

publicoverridestringName

get=>base.Name; protectedset { if(!string.IsNullOrEmpty(value)) base.Name=value;

//Or
{
}
{
}
{
{
} } } Hoofdstuk1 –Werkenmetgegevenstypen 10

//Originalversion publicclassPerson

Uhebttweeextravoordelenwanneeruimplicieteeigenschappengebruikt. Teneerste:wanneerulaterdeimplicieteeigenschapwiltvervangendooreen concreteimplementatievoorgegevensvalidatieofandereacties,danmaaktu binair-compatibelewijzigingenbinnendeklasse.Tentweede:devalidatiekomt slechtsopéénlocatieterecht.

IneerdereversiesvanC#benaderden demeesteontwikkelaarshetbacking fieldrechtstreeksomhetbinnendeeigenklassetewijzigen.Diewerkwijze produceertcodediedevalidatieenfoutcontroleverspreidtdoorhetgehele bestand.Elkewijziginginhetbackingfieldvaneenimplicieteeigenschaproept de(eventueelprivate)eigenschapsaccessoraan.Veranderdaaromdeimplicieteeigenschapsaccessorineenexplicieteeigenschapsaccessorenschrijfdan allecodevoordevalidatieindenieuweaccessor:

publicstringFirstName{get;set;} publicstringLastName{get;set;} publicoverridestringToString()=>

$"{FirstName}{LastName}“;

//Laterupdatedforvalidation publicclassPerson

publicPerson(stringfirstName,stringlastName)

//Leveragevalidationinpropertysetters: this.FirstName=firstName; this.LastName=lastName;

privatestringfirstName; publicstringFirstName

get=>firstName; set {

if(string.IsNullOrEmpty(value)) thrownewArgumentException( “Firstnamecannotbenullorempty”); firstName=value;

{
}
{
{
}
{
} } 11 Handboek– EffectieverprogrammereninC#

privatestringlastName; publicstringLastName { get=>lastName; privateset

{ if(string.IsNullOrEmpty(value)) thrownewArgumentException( “Lastnamecannotbenullorempty”); lastName=value;

publicoverridestringToString()=> $"{FirstName}{LastName}“;

Wanneeruimplicieteeigenschappengebruikt,dankomtallevalidatieopéén plaatsterecht.Alsudeaccessorkuntblijvengebruikeninplaatsvanhetbackingfieldrechtstreekstebenaderen,dan blijftalleveldvalidatieopéénlocatie.

Implicieteeigenschappenhebbenéénbelangrijkebeperking:uzenietgebruikenoptypenmethetattribuut Serializable.Debestandsindelingvoorpersistenteopslagisafhankelijkvandeveldnaamvandedoordecompilergegenereerdebackingstore.Erisgeengarantiedatdieveldnaamhetzelfdeblijft, datwilzeggen,dienaamkanveranderentelkenswanneerudeklasseaanpast.

Ondankshunbeperkingenbesparenimplicieteeigenschappenontwikkelingstijd,zeproducerenleesbarecode,enzebevordereneenstijlvanontwikkeling waarinallevalidatievoorveldwijzigingenopéénlocatiegebeurt.Alsuwcode overzichtelijkeris,danishetonderhoudvandiecodeookeenvoudiger.

Advies3:Kiesvoorconstantevalue-typen

Constanten(immutabletypes)zijneenvoudigtebegrijpen:nadatzezijn gemaakt,houdenzeeenconstantewaarde.Alsudeparametersvalideert waarmeeuhetobjectconstrueert,dankuntuerzekervanzijndathetobject vanafdatpunteengeldigestatusheeftenhoudt;ukuntimmersdeinterne statusvanhetobjectnietmeerwijzigen.Daarmeekanookdefoutcontrole achterwegeblijvenomdatergeenstatuswijzigingenmeermogelijkzijnnadat hetobjectisgebouwd.Deconstantetypenzijninherentveiligtegebruikenin threads:meerderelezerskunnendezelfdeinhoudbenaderen.Alsdeinterne statusnietkanveranderen,ishetonmogelijkdatverschillendethreadsincon-

}
}
}
Hoofdstuk1 –Werkenmetgegevenstypen 12

sistenteweergavenvandegegevenszien.Constantetypenkuntuveiligexporterenvanuituwobjecten,omdatdeaanroeperdeinternestatusvanuwobjectennietkanwijzigen.

Constantetypenwerkenbeterinverzamelingenmethashcode.Dewaardedie wordtgeretourneerddoor Object.GetHashCode() moeteenconstante instantiezijn(zieadvies10);datisaltijdhetgevalvoorconstantetypen.

Indepraktijkishetheelmoeilijkomelktypeconstanttemaken.Daaromisdit adviesvantoepassingopzowelatomaire alsconstantevalue-typen.Ontbindt uwtypeninstructurendieopnatuurlijke wijzeeenenkeleentiteitvormen.Het typeAdresvormteenzo’nentiteit.Eenadresiséénitemdatbestaatuitverschillendegerelateerdevelden,eneenwijziginginéénveldbetekentwaarschijnlijkookwijzigingeninanderevelden.HettypeKlantisdaarentegengeen atomairtype.Eenklanttypebevatwaarschijnlijkveelgegevens,zoalseen adres,eennaameneenofmeertelefoonnummers,enelkvandezeonafhankelijkegegevenskanwordengewijzigd.Zokaneenklantvantelefoonnummer veranderenzonderteverhuizen.Alseen klantverhuist,kandezewelhetzelfde telefoonnummerbehouden.Eneenklantkanzijnofhaarnaamwijzigenmet behoudvantelefoonnummerenzondervanadresteveranderen.Eenklantobjectisnietatomair;hetissamengestelduitveelverschillendeconstante typen–eenadres,eennaam,ofeenverzamelingvantelefoonnummeren meer.Atomairetypenzijnenkeleentiteiten:bijeenwijzigingishetlogischom degeheleinhoudtevervangen.Deuitzonderinghieropiswanneerueenvan desamenstellendeveldenwijzigt.

Hieriseentypischeimplementatievaneenvariabel(mutable)adres:

//MutableAddressstructure publicstructAddress {

privatestringstate; privateintzipCode;

//Relyonthedefaultsystem-generated

//constructor publicstringLine1{get;set;} publicstringLine2{get;set;} publicstringCity{get;set;} publicstringState

get=>state; set

{
13 Handboek– EffectieverprogrammereninC#

ValidateState(value); state=value; }

publicintZipCode { get=>zipCode; set {

ValidateZip(value); zipCode=value; }

//Otherdetailsomitted }

//Exampleusage:

Addressa1=newAddress(); a1.Line1=“111S.Main”; a1.City=“Anytown”; a1.State=“IL”; a1.ZipCode=61111;

//Modify: a1.City=“AnnArbor”;//Zip,Stateinvalidnow a1.ZipCode=48103;//Statestillinvalidnow a1.State=“MI”;//Nowfine

Internestatusveranderingenbetekenendathetmogelijkisomdeonveranderlijkheidvanhetobjectteschenden,althanstijdelijk.NadatuhetveldCityhebt gewijzigd,krijgthetobjecta1eenongeldigestatus.Deplaatsisveranderden komtnietmeerovereenmetdeinhoudvandeveldenStateenZipCode.De codezieteronschuldiggenoeguit,maar steldatditfragmentonderdeelisvan eenmultithreadedprogramma:elkewijzigingindecontextnadewijzigingin CityenvoordeaanpassingvanStateofZipCodekanleidentoteeninconsistenteweergavevandegegevensineenanderethread.

Zelfsalsugeenmultithreadedprogrammaschrijft,dankuntutochindeproblemenkomenbijveranderingvandeinternestatus.Steldatdeinhoudvan hetveldZipCodeongeldigis,zodatseteenexceptiongenereert.Uhebtnog nietallewijzigingenaangebracht, maarnuheefthetsysteemeenongeldige status.Omditprobleemteverhelpen,moetuaanzienlijkehoeveelheidinterne

{
}
}
Hoofdstuk1 –Werkenmetgegevenstypen 14

valideringscodetoevoegenaandeadresstructuur.Dievalideringscodeverhoogtopzijnbeurtdeomvangendecomplexiteitvanuwtotalecode.Alsu volledigebeveiligingvoorexceptionswiltimplementeren,danzouubeveiligingscodemoetenschrijvenvoorelkcodeblokwaarinumeerdanéénveldverandert.Threadsafetyvereisthettoevoegenvansignificantethreadsynchronisatiecontrolesvoorelkeeigenschapsaccessor,zowelsetalsget.Almetalisdat veelwerk–endatwordtwaarschijnlijkmeerwanneerulaternieuwefuncties toevoegt.

Alsuhetadresobjectnodighebtals struct,daniseenbetereaanpakomhet constantof immutable temaken.Maakeerstalleinstantieveldenread-only voorexterngebruik.

publicstructAddress

//Remainingdetailselided publicstringLine1{get;} publicstringLine2{get;} publicstringCity{get;} publicstringState{get;} publicintZipCode{get;}

publicAddress(stringline1, stringline2, stringcity, stringstate, intzipCode): this()

Line1=line1; Line2=line2; City=city; ValidateState(state); State=state; ValidateZip(zipCode); ZipCode=zipCode;

Nuhebtueenconstanttype,gebaseerdopdepublicinterface.Schrijfnualle benodigdeconstructorsvoordeinitialiseringvan Address-structuur.Deze structuurheeftslechtséénextraconstructornodig,waarbijelkveldwordt opgegeven.Eenkopieerconstructorisnietnodigomdatdetoewijzingsoperator netzoefficiëntis.Onthouddatdestandaardconstructornogsteedstoeganke-

{
{
} }
15 Handboek– EffectieverprogrammereninC#

lijkis.Eriseenstandaardadreswaarallestringsdewaardenullhebbenende zipcodedewaarde0.

publicAddress(stringline1, stringline2, stringcity, stringstate, intzipCode): this() {

Line1=line1; Line2=line2; City=city; ValidateState(state); State=state; ValidateZip(zipCode); ZipCode=zipCode;

//Createanaddress:

Hetgebruikvanhetconstantetypevereisteenietsandereaanroepvoorhet wijzigenvanzijnstatus.Umaaktnamelijkeennieuwobjectinplaatsvanhet bestaandeexemplaaraantepassen:

Addressa2=newAddress(“111S.Main”, “”,“Anytown”,“IL”,61111);

//Tochange,re-initialize: a2=newAddress(a1.Line1, a1.Line,“AnnArbor”,“MI”,48103);

Dewaardevana1vindtuopeenvantweelocaties:Anytownopdeoriginele locatieofAnnArboropdebijgewerktelocatie.Uwijzigtniethetbestaande adres,daarmeegenereertudeongeldigetijdelijkestatuszoalsinhetvorige voorbeeld.Detussentijdselocatiesbestaanslechtstijdensdeuitvoeringvande adresconstructorenzijnnietzichtbaar buitendieconstructor.Zodraeennieuw adresobjectisgemaakt,wordtdewaardeervanvooraltijdvastgelegd.Deze codeisook exceptionsafe:a1heeftofweldeoorspronkelijkewaardeofde nieuwewaarde.Alstijdensdebouwvanhetnieuweadresobjecteenexception wordtgegenereerd,isdeoorspronkelijkewaardevana1ongewijzigd.

Alsueenconstanttypecreëert,moetuervoorzorgendatuwcodegeengaten heeftdiecliëntentoestaanomdeinternestatusteveranderen.Value-typen biedengeenondersteuningvoorafgeleidetypen,dusuhoeftgeenbeveiliging

}
Hoofdstuk1 –Werkenmetgegevenstypen 16

intebouwenvoorafgeleidetypendieveldenwijzigen.Echter,ineenconstant typemoetuweloppassenmetelkvelddatverwijstnaareenvariabelreference-type.Wanneeruconstructorsvoordezetypenimplementeert,moetu eenbeveiligingskopievandatvariabeletypemaken.Indevolgendevoorbeeldenwordtervanuitgegaandat Phone eenconstantvalue-typeis,omdatwe onshieralleenbezighoudenmetconstantevalue-typen:

//Almostimmutable:Thereareholesthatwould

//allowstatechanges.

publicstructPhoneList

privatereadonlyPhone[]phones;

publicPhoneList(Phone[]ph)

phones=ph;

publicIEnumerable<Phone>Phones { get{returnphones;}

Phone[]phones=newPhone[10];

//Initializephones

PhoneListpl=newPhoneList(phones);

//Modifythephonelist:

//alsomodifiestheinternalsofthe(supposedly)

//immutableobject. phones[5]=Phone.GeneratePhoneNumber();

Dearrayklasseiseenreference-type.Inditvoorbeeldverwijstdearraybinnen de struct PhoneListnaardezelfdegeheugenlocatievandearrayPhonesdieis toegewezenbuitenhetobject.Datwilzeggendatontwikkelaarsnuuwconstantestructuurkunnenwijzigenmeteen anderevariabeledienaardezelfde opslaglocatieverwijst.Uelimineertdezemogelijkheidmeteenveiligheidskopie vandearray. Array iseenvariabeltype,dusdeklasse ImmutableArray vande namespace System.Collections.Immutable zoueenalternatiefkunnenzijn. Hetvorigevoorbeeldtoontdevalkuilenvaneenvariabeleverzameling.Alshet type Phone eenvariabelreference-typeis,zijnernogmeermogelijkheden voorellende.Eenclientkandandewaardenvandeverzamelingwijzigen,zelfs

{
{
}
} }
17 Handboek– EffectieverprogrammereninC#

lsdeverzamelingisbeveiligdtegenwijziging.Ditprobleemiseenvoudigte verhelpenalsuhettype ImmutableList gebruikt:

publicstructPhoneList

privatereadonlyImmutableList<Phone>phones;

publicPhoneList(Phone[]ph)

phones=ph.ToImmutableList();

publicIEnumerable<Phone>Phones=>phones;

Erzijndriestrategieëndieukuntgebruiken.Decomplexiteitvanhettype bepaaltwelkevandedrieuhetbestekunt gebruikenvoorhetinitialiserenvan uwconstantetype.Teneerste,ukuntéénconstructordefiniërenwaarmee clientseenobjectkunneninitialiseren.Neembijvoorbeelddeadresstructuur waarbijeenconstructorisgedefinieerdwaarmeeclientseenadreskunneninitialiseren.Hetopzettenvandebenodigdeconstructeursisvaakdeeenvoudigsteaanpak.

Tentweede,ukuntfactorymethodenmakenomdestructuurteinitialiseren. Factory’smakenhetmakkelijkeromgemeenschappelijkewaardentecreëren. Het.NETFrameworktype Color gebruiktdezestrategieomsysteemkleurente initialiseren.Destatischemethoden Color.FromKnownColor() en Color. FromName() retournereneenkopievaneen kleurwaardediedehuidige waardevooreenbepaaldesysteemkleurvertegenwoordigt.

Tenderde,ukunteenvariabelecompanionklassemakenwanneermeerstapsoperatiesnodigzijnvoordevolledige constructievaneenconstanttype.De stringklassevan.NETgebruiktdezestrategiemetdeklasse System.Text. StringBuilder.Metdeklasse StringBuilder vultueenstringinopeenvolgendestappen.Nadatallebewerkingendienodigzijnomdestringtebouwen klaarzijn,haaltudeconstantestringopin StringBuilder

Deconstantetypenzijneenvoudigerteschrijvenengemakkelijkerteonderhouden.Schrijfnietblindelingsget-enset-accessorsvoorelkeeigenschapvan eentype.ImplementeerInplaatsdaarvan,wanneereentypegegevens opslaat,dezedanalsconstante,atomairevalue-typen.Ubouwtmetdezeentiteiteneenvoudigingewikkeldestructuren.

{
{
}
}
Hoofdstuk1 –Werkenmetgegevenstypen 18
Issuu converts static files into: digital portfolios, online yearbooks, online catalogs, digital photo albums and more. Sign up and create your flipbook.