Properties
Properties
In dit hoofdstuk bespreken we eerst waarom properties nodig zijn. Vervolgens bespreken we de 2 soorten properties die er bestaan:
Full properties
Auto properties
In een wereld zonder properties
Properties (eigenschappen) zijn de C# manier om objecten hun interne staat in en uit te lezen. Ze zorgen voor een gecontroleerde toegang tot de interne structuur van je objecten.
Stel dat we volgende klasse hebben:
Een SithLord
heeft steeds een verborgen Sith Name en ook een hoeveelheid energie die hij nodig heeft om te strijden. Het is uit den boze dat we eenvoudige data fields (energy
en name
) public
maken. Zouden we dat wel doen dan kunnen externe objecten deze geheime informatie uitlezen!
We willen echter wel van buiten uit het energy-level van een SithLord
kunnen instellen. Maar ook hier hetzelfde probleem: wat als we de energy-level op -1000
instellen? Terwijl energy
nooit onder 0
mag gaan.
Properties lossen dit probleem op
Oldschool oplossing
Vroeger loste men voorgaande probleem op door Get-methoden te schrijven:
Je zal deze manier nog in veel andere talen tegenkomen. Wij prefereren properties zoals we nu zullen uitleggen.
Je zou dan kunnen doen:
Full properties
Een full property ziet er als volgt uit:
Dankzij deze code kunnen we nu elders dit doen:
Vergelijk dit met de vorige alinea waar we dit met Get en Set methoden moesten doen. Deze property syntax is veel eenvoudiger in het gebruik.
We zullen de property nu stuk per stuk analyseren:
public int Energy
: een property is normaalpublic
. Vervolgens zeggen we wat voor type de property moet zijn en geven we het een naam. Indien je de property gaat gebruiken om een intern dataveld naar buiten beschikbaar te stellen, dan is het een goede gewoonte om dezelfde naam als dat veld te nemen maar nu met een hoofdletter. (dusEnergy
i.p.v.energy
).{ }: Vervolgens volgen 2 accolades waarbinnen we de werking van de property beschrijven.
get {}
: indien je wenst dat de property data naar buiten moet sturen, dan schrijven we de get-code. Binnen de accolades van de get schrijven we wat er naar buiten moet gestuurd worden. In dit gevalreturn energy
maar dit mag even goed bijvoorbeeldreturn 4
of een hele reeks berekeningen zijn. Het element dat je returnt in de get code moet uiteraard van hetzelfde type zijn als waarmee je de property hebt gedefinieerd (int
in dit geval).We kunnen nu van buitenaf toch de waarde van
energy
uitlezen via de property en het get-gedeelte:Console.WriteLine(palpatine.Energy);
set{}: in het set-gedeelte schrijven we de code die we moeten hanteren indien men van buitenuit een waarde aan de property wenst te geven om zo een interne variabele aan te passen. De waarde die we van buitenuit krijgen (als een parameter zeg maar) zal altijd in een lokale variabele
value
worden bewaard. Deze zal van het type van de property zijn. Vervolgens kunnen wevalue
toewijzen aan de interne variabele indien gewenst:energy=value
We kunnen vanaf nu van buitenaf waarden toewijzen aan de property en zo
energy
vtoch bereiken:palpatine.Energy=50
.
Snel property schrijven
Visual Studio heeft een ingebouwde shortcut om snel een full property, inclusief een bijhorende private dataveld, te schrijven. Typ propfull
gevolgd door twee tabs!
Full property met toegangscontrole
De full property Energy
heeft nog steeds het probleem dat we negatieve waarden kunnen toewijzen (via de set
) die dan vervolgens zal toegewezen worden aan energy
.
Properties hebben echter de mogelijkheid om op te treden als wachters van en naar de interne staat van objecten.
We kunnen in de set
code extra controles inbouwen. Asl volgt:
Enkel indien de toegewezen waarde groter of gelijk is aan 0 zal deze ook effectief aan energy
toegewezen worden. Volgende lijn zal dus geen effect hebben: palpatine.Energy=-1;
We kunnen de code binnen set
(en get
) zo complex als we willen maken.
Property variaties
We zijn niet verplicht om zowel de get
en de set
code van een property te schrijven.
Write-only property
We kunnen dus enkel energy
een waarde geven, maar niet van buitenuit uitlezen.
Read-only property
We kunnen dus enkel energy
van buitenuit uitlezen, maar niet aanpassen.
Read-only property met private set
Soms gebeurt het dat we van buitenuit enkel de gebruiker de property read-only willen maken. We willen echter intern (in de klasse zelf) nog steeds controleren dat er geen illegale waarden aan private datafields worden gegeven. Op dat moment definieren we een read-only property met een private setter:
Van buitenuit zal enkel code werken die deget
-van deze property aanroept: Console.WriteLine(palpatine.Energy);
. Code die de set
van buitenuit nodig heeft zal een fout geven zoals: palpatine.Energy=65
; ongeacht of deze geldig is of niet.
Nu goed opletten: indien we in het object de property willen gebruiken dan moeten we deze dus ook effectief aanroepen, anders omzeilen we hem als we rechtstreeks energy
instellen.
Kijk zelf naar volgende slechte code:
De nieuw toegevoegde methode ResetLord
willen we gebruiken om de lord z'n energy terug te verlagen. Door echter energy=-1
te schrijven geven we dus -1 rechtstreeks aan energy
. Nochtans is dit een illegale waarde. We moeten dus in de methode ook expliciet via de property gaan en dus schrijven:
Het is een goede gewoonte om zo vaak mogelijk via de properties je interne variabele aan te passen en niet rechtstreeks het dataveld zelf.
Read-only Get-omvormers
Je bent uiteraard niet verplicht om voor iedere interne variabele een bijhorende property te schrijven. Omgekeerd ook: mogelijk wil je extra properties hebben voor data die je 'on-the-fly' kan genereren.
Stel dat we volgende klasse hebben
We willen echter ook soms de volledige naam op het scherm tonen ("Voornaam + Achternaam"). Via een read-only property kan dit supereenvoudig:
Of nog eentje:
Nog een voorbeeldje:
Vaak gebruiken we dit soort read-only properties om data te transformeren. Stel bijvoorbeeld dat we volgende klasse hebben:
Auto properties
Automatische eigenschappen (autoproperties) in C# staan toe om eigenschappen (properties) die enkel een waarde uit een private variabele lezen en schrijven verkort voor te stellen.
Zo kan je eenvoudige de klasse Person herschrijven met behulp van autoproperties. De originele klasse:
De herschreven klasse met autoproperties (autoprops):
Beide klassen hebben exact dezelfde functionaliteit, echter de klasse aan de rechterzijde is aanzienlijk eenvoudig om te lezen en te typen.
Beginwaarde van autoprops
Je mag autoproperties beginwaarden geven door de waarde achter de property te geven, als volgt:
Altijd auto-properties?
Merk op dat je dit enkel kan doen indien er geen extra logica in de property aanwezig is. Stel dat je bij de setter van age wil controleren op een negatieve waarde, dan zal je dit zoals voorheen moeten schrijven en kan dit niet met een automatic property:
Voorgaande property kan dus NIET herschreven worden met een automatic property.
Alleen-lezen eigenschap
Je kan automatic properties ook gebruiken om bijvoorbeeld een read-only property te definiëren . Als volgt:
Originele klasse:
Met autoprops:
En andere manier die ook kan is als volgt:
De enige manier om FirstName een waarde te geven is via de constructor van de klasse. Alle andere manieren zal een error genereren.Meer info.
Snel autoproperties typen in Visual Studio:
Als je in Visual Studio in je code prop
typt en vervolgens twee keer de tabtoets indrukt dan verschijnt al de nodige code voor een automatic property. Je hoeft dan enkel nog volgende zaken in orde te brengen:
Het type van de property
De naam van de property (identifier)
De toegankelijkheid van get/set (public, private, protected)
Via propg
krijg je aan autoproperty met private setter.
Methode of property
Een veel gestelde vraag bij beginnende OO-ontwikkelaars is: "Moet dit in een property of in een methode gestoken worden?"
De regel is eenvoudig:
Betreft het een actie, iets dat het object moet doen (tekst tonen, iets berekenen, etc) dan plaats je het in een methode
Betreft het een eigenschap die een bepaalde waarde heeft, dan gebruik je een property
Last updated