Az objektumorientált programozási nyelvek előnye, hogy szabályozhatjuk a változókhoz való hozzáférést is. Azonban adódhat olyan helyzet, amikor azt szeretnénk elérni, hogy egy belső változó értéke ne lehessen nagyobb, mint 60000. Ekkor egy megoldás az lenne, hogy privát láthatóságúvá tesszük az adattagot és írunk egy lekérdező, meg egy beállító függvényt, amin keresztül az adattag biztonságosan, a meghatározott keretek között lekérdezhető és beállítható. Az alábbi példa egy ilyen esetet mutat be:
using System;
namespace PeldaGetsetMetodus
{
class GetSetMetodus
{
private int _adattag;
public int GetAdattag()
{
return _adattag;
}
public void SetAdattag(int adat)
{
if (adat > 60000) _adattag = 60000;
else _adattag = adat;
}
}
class Program
{
static void Main(string[] args)
{
var pelda = new GetSetMetodus();
pelda.SetAdattag(48000);
Console.WriteLine(pelda.GetAdattag());
pelda.SetAdattag(1200000);
Console.WriteLine(pelda.GetAdattag());
Console.ReadKey();
}
}
}
A program kimenete:
48000
60000
A probléma ezzel a megoldással az, hogy feleslegesen növeli egy osztály metódusainak a számát. Ezen megközelítést nevezzük getter és setter metódusoknak, mivel ezek lekérik vagy beállítják egy objektum belső adattagjait. Java és C++ esetén ajánlott kódolási konvenció, hogy az ilyen beállító és lekérdező metódusok nevét get vagy set szóval kezdjük, attól függően, hogy mit végez a metódus. Ezen szót követően pedig a belső adattag nevét kellene írni.
Ezen metódusok használata a szintaxisból következően nem éppen kényelmes, illetve azért sem, mert sok minden függ a fejlesztő jóságától, vagyis hogy betartja-e a kódolási konvenciót. (Ez alatt konkrétan az értendő, hogy a lekérdező metódusok nevét mondjuk Get, az írókat pedig Set szóval kezdi, mert a DoValamiKismacskaRelatedStuff() metódusnévből nem következik, hogy az mondjuk a kódban az áfakulcs értékét állítja be.)
Ezért a C# nyelvi elemként támogatja a tulajdonságok létrehozását. Szemléltetésképpen az előző példában megvalósított Get, Set függvényt kiváltom egy tulajdonsággal:
using System;
namespace PeldaProperty
{
class Property
{
private int _adattag;
public int Adattag
{
get { return _adattag; }
set
{
if (value > 60000) _adattag = 60000;
else _adattag = value;
}
}
}
class Program
{
static void Main(string[] args)
{
var pelda = new Property();
pelda.Adattag = 48000;
Console.WriteLine(pelda.Adattag);
pelda.Adattag = 1200000;
Console.WriteLine(pelda.Adattag);
Console.ReadKey();
}
}
}
A program kimenete:
48000
60000
A tulajdonságok deklarálása hasonlít a metódus definiáláshoz. Kell egy visszatérési típus és egy név, de zárójelek és paraméterek nem kellenek. A blokkban lehet egy get blokk, ami értéket ad vissza a return kulcsszóval. Továbbá lehet egy set blokk is, ami értéket állít be. A paraméterként kapott érték a value kulcsszó segítségével érhető el. A get, set, value szavak kontextusfüggő kulcsszavak. Ez azt jelenti, hogy használhatjuk őket változónévként, mivel csak egy adott kontextusban van különös szerepük.
A kész tulajdonságunk ezután a változóknál megszokott szintaxissal kezelhető. További előnye a tulajdonságoknak, hogy a set és get blokk előtt alkalmazható a private vagy protected módosító is. Így ezek csak a módosított szerepkörön belül érhetőek el.
A tulajdonságok speciális fajtája az automatikusan definiált. Szintaxisuk a következő:
public int Adattag
{
get;
set;
}
Ezen szintaxisnak akkor van értelme, ha az adattagunkat csak olvashatóvá szeretnénk tenni az osztályon kívül, de nem akarunk belső változót létrehozni, mert felesleges lenne erre a célra logika hiányában.
Ehhez csupán azt kell tennünk, hogy a set kulcsszó elé beillesztjük a private módosítót, így az osztályon belül a tulajdonság írható marad, de az osztályon kívül már csak olvasható. A tulajdonságoknak továbbá nagy szerepe van az adatkötések során. Adatkötésben nem használhatunk változókat, csak tulajdonságokat. Erről természetesen részletesebben lesz szó.
Továbbá akkor érdemes automatikusan létrehozott tulajdonságokat még alkalmazni, ha az osztályból adattagokat kell kipublikálnunk, de nincs szükségünk az adott pillanatban get és set logikára. Ha később mégis szükség lenne ilyenre, akkor az biztos, hogy kisebb módosítás lesz, mint ha a kipublikált mezőt kellene átírnunk tulajdonságra.