A tulajdonságokhoz való hozzáférés korlátozása

Befejeződött

Az osztály meghatározhatja, hogy az egyes tagok milyen módon legyenek elérhetők az osztályon kívüli kódhoz. Az osztályon vagy szerelvényen kívülről nem használható metódusok és változók rejtve lehetnek a kódolási hibák vagy rosszindulatú kihasználások lehetőségének korlátozása érdekében.

Egyes metódusokat és tulajdonságokat egy osztályon kívüli kódból, más néven ügyfélkódból kell meghívni vagy elérni. Más metódusok és tulajdonságok csak az osztályban használhatók. Fontos korlátozni a kód akadálymentességét, hogy csak a kívánt ügyfélkód érhesse el. A következő hozzáférési módosítók használatával adhatja meg, hogy a típusok és a tagok milyen módon legyenek elérhetők az ügyfélkódhoz:

  • public: A típust vagy tagot az ugyanabban a szerelvényben lévő bármely más kód vagy egy rá hivatkozó másik szerelvény is elérheti.
  • protected: A típus vagy tag csak kóddal érhető el ugyanabban az osztályban vagy származtatott osztályban.
  • internal: A típust vagy tagot ugyanannak a szerelvénynek bármely kódja elérheti, egy másik szerelvényből azonban nem.
  • protected internal: A típust vagy tagot egy szerelvény bármely kódja vagy egy másik szerelvény bármely származtatott osztálya elérheti.
  • private: A típus vagy tag csak kóddal érhető el ugyanabban az osztályban vagy szerkezetben.
  • private protected: A típus vagy tag csak kód alapján érhető el ugyanabban a szerelvényben, és csak az ugyanabban az osztályban vagy származtatott osztályban lévő kód alapján.

Az osztálytagok alapértelmezés szerint private hozzáféréssel vannak hozzárendelve.

A tulajdonságok és tartozékok módosítóinak elérése

A modul ezen pontig a get és set tartozékait tartalmazó tulajdonságokra összpontosítottunk. Ezeket a tulajdonságokat írási-olvasási tulajdonságoknak nevezzük. Az írási-olvasási tulajdonságok mellett írásvédett tulajdonságokat is létrehozhat, vagy különböző kisegítő lehetőségeket biztosíthat a set és get tartozékai számára.

Alapértelmezés szerint get és set tartozékai ugyanolyan kisegítő szinttel rendelkeznek, mint az a tulajdonság, amelyhez tartoznak. Azonban korlátozhatja a get vagy set tartozék elérhetőségét. A hozzáférési módosítók akkor hasznosak, ha korlátozni szeretné a tulajdonsághoz való hozzáférést, de továbbra is engedélyezi a tulajdonság értékéhez való hozzáférést egy get tartozékon keresztül.

Tegyük fel, hogy van egy Person osztálya, amely csak a FirstName tulajdonság értékének módosítását engedélyezi az osztály más metódusaitól. Belső vagy nyilvános helyett privát akadálymentességet biztosíthat a set tartozéknak:


public class Person
{
    public string? FirstName { get; private set; }

    // Omitted for brevity.
}

A FirstName tulajdonság bármely kódból olvasható, de csak a Person osztály kódjából rendelhető hozzá.

Bármilyen korlátozó hozzáférés-módosító hozzáadható a set vagy get tartozékhoz. Az egyes tartozékokon a hozzáférés-módosítónak szigorúbbnak kell lennie, mint a tulajdonsághoz való hozzáférés. Az előző kód azért jogi, mert a FirstName tulajdonság public, de a set tartozék private. Nem deklarálhat private tulajdonságot public tartozékkal. A tulajdonságdeklarációk protected, internal, protected internalvagy akár privateis deklarálhatók.

A set tartozékaihoz két speciális hozzáférési módosító használható:

  • Egy set tartozék hozzáférés-módosítóként init is rendelkezhet. Ez a set tartozék csak egy objektum inicializálójától vagy a típus konstruktoraitól hívható meg. Szigorúbb, mint a private tartozék set.
  • Az automatikusan implementált tulajdonság get tartozék nélkül deklarálhat set tartozékot. Ebben az esetben a fordító lehetővé teszi, hogy a set tartozék csak a típus konstruktoraiból legyen meghívva. Szigorúbb, mint a init tartozék set tartozéka.

Fontolja meg a Person osztály következő frissítéseit:


public class Person
{
    public Person(string firstName) => FirstName = firstName;

    public string FirstName { get; }

    // Omitted for brevity.
}

Az előző példában a hívóknak a FirstName paramétert tartalmazó konstruktort kell használniuk. A hívók nem használhatnak objektum inicializálókat, hogy értéket rendeljenek a tulajdonsághoz. Az inicializálók támogatásához a set tartozékot init kiegészítővé teheti, ahogyan az alábbi kódban látható:


public class Person
{
    public Person() { }
    public Person(string firstName) => FirstName = firstName;

    public string? FirstName { get; init; }

    // Omitted for brevity.
}

Ezeket a módosítókat gyakran használják a required módosítóval a megfelelő inicializálás kényszerítéséhez.

A tartozék akadálymentességének korlátozása

Bizonyos esetekben hasznos lehet korlátozni a get vagy set tartozékhoz való hozzáférést. Általában korlátozza a set tartozék akadálymentességét, miközben a get tartozék nyilvánosan elérhető marad.

Például:


private string _name = "Hello";

public string Name
{
    get
    {
        return _name;
    }
    protected set
    {
        _name = value;
    }
}

Ebben a példában egy Name nevű tulajdonság definiál egy get és set tartozékot. A get tartozék maga a tulajdonság akadálymentességi szintjét kapja, public ebben az esetben, míg a set tartozék kifejezetten korlátozott, ha a protected hozzáférési módosítóját alkalmazza magára a tartozékra.

A tartozékokkal kapcsolatos hozzáférési módosítók korlátozásai

A tartozékmódosítók tulajdonságokon vagy indexelőkön való használatára a következő feltételek vonatkoznak:

  • A kiegészítő módosítókat csak akkor használhatja, ha a tulajdonság set és get tartozékokkal is rendelkezik. Ebben az esetben a módosító csak a két tartozék egyikén engedélyezett.
  • A tartozék akadálymentességi szintjének szigorúbbnak kell lennie, mint magának a tulajdonságnak vagy indexelőnek az akadálymentességi szintje.

Írásvédett statikus tulajdonságok

Az alábbi példa a példány és a statikus tulajdonságok osztályban való használatát mutatja be.

A Employee osztálynak van egy Counter nevű statikus tulajdonsága, amely nyomon követi a létrehozott osztálypéldányok számát. A Counter tulajdonság írásvédett, ami azt jelenti, hogy az osztályon kívülről is elérhető, de nem módosítható. A Counter tulajdonság is static, ami azt jelenti, hogy a Counter értéket az Employee osztály használatával éri el, nem az osztály employee1 vagy employee2 példányaival.


public class Employee
{
    public static int NumberOfEmployees;
    private static int _counter;
    private string _name;

    // A read-write instance property:
    public string Name
    {
        get => _name;
        set => _name = value;
    }

    // A read-only static property:
    public static int Counter => _counter;

    // A Constructor:
    public Employee() => _counter = ++NumberOfEmployees; // Calculate the employee's number:
}

public class Program
{
    static void Main(string[] args)
    {
        // Create an initial instance of the Employee class
        Employee employee1 = new Employee { Name = "NameOne" };
        
        // Display the name and counter values
        Console.WriteLine($"Employee 1: Name = {employee1.Name}, Counter = {Employee.Counter}");

        // Create a second instance of the Employee class
        Employee employee2 = new Employee { Name = "NameTwo" };

        // Display the name and counter values
        Console.WriteLine($"Employee 2: Name = {employee2.Name}, Counter = {Employee.Counter}");

        employee2.Name = "NameThree";

        // Display the name and counter values
        Console.WriteLine($"Employee 2: Name = {employee2.Name}, Counter = {Employee.Counter}");

        // Keep the console window open in debug mode.
        Console.WriteLine("Press any key to exit.");
        Console.ReadKey();
    }
}

A Employee osztály a következő tagokat tartalmazza:

  • NumberOfEmployees: Nyilvános statikus mező, amely nyomon követi a létrehozott alkalmazotti példányok teljes számát. Mivel statikus, az Alkalmazott osztály összes példánya között meg van osztva.
  • _counter: Egy privát statikus mező, amely egyedi számot rendel minden alkalmazotti példányhoz. Az összes példány között is meg van osztva.
  • _name: Az alkalmazott nevét tároló privát példány mező. Ez az Alkalmazott osztály minden egyes példányára vonatkozik.
  • Name: Nyilvános írásvédett példánytulajdonság, amely hozzáférést biztosít a _name mezőhöz. A get tartozék visszaadja a _nameértékét , és a set tartozék új értéket rendel _name.
  • Counter: Nyilvános írásvédett statikus tulajdonság, amely hozzáférést biztosít a _counter mezőhöz. A get tartozék a _counterértékét adja vissza. A Counter tulajdonság az objektum helyett az osztályhoz van társítva, mert statikus tulajdonságként van definiálva.

A két statikus mező inicializálódik, amikor az osztály először betöltődik a memóriába, mielőtt az osztály bármely példánya létrejön. A C#-ban a statikus mezők inicializálása az alapértelmezett értékükre történik, ha nincs explicit inicializálva. int mezők esetében az alapértelmezett érték 0.

A statikus tulajdonságok és mezők magukhoz az osztályhoz tartoznak, nem pedig az osztály egy adott példányához. Az osztály minden példánya ugyanazokkal a statikus tulajdonságokkal és mezőkkel rendelkezik.

A konstruktor 1-gyel növeli a NumberOfEmployees statikus mezőt, és hozzárendeli az új értéket a _counter statikus mezőhöz. Ez a módszer biztosítja, hogy minden Employee példány egyedi számot kapjon.

Privát tartozékok

Vegye figyelembe az olvasási-írási tulajdonságokat megvalósító alábbi kódot:


class Person
{
    private string _name = "N/A";
    private int _age = 0;

    // Declare a Name property of type string:
    public string Name
    {
        get
        {
            return _name;
        }
        set
        {
            _name = value;
        }
    }

    // Declare an Age property of type int:
    public int Age
    {
        get
        {
            return _age;
        }
        set
        {
            _age = value;
        }
    }
}

class TestPerson
{
    static void Main()
    {
        // Create a new Person object:
        Person person = new Person();

        // Print out the name and the age associated with the person:
        Console.WriteLine($"Person details - Name = {person.Name}, Age = {person.Age}");

        // Set some values on the person object:
        person.Name = "NameOne";
        person.Age = 99;
        Console.WriteLine($"Person details - Name = {person.Name}, Age = {person.Age}");

        // Increment the Age property:
        person.Age += 1;
        Console.WriteLine($"Person details - Name = {person.Name}, Age = {person.Age}");

        // Keep the console window open in debug mode.
        Console.WriteLine("Press any key to exit.");
        Console.ReadKey();
    }
}

/* Output:
Person details - Name = N/A, Age = 0
Person details - Name = NameOne, Age = 99
Person details - Name = NameOne, Age = 100
*/

Ebben a példában a Person osztály Name és Age tulajdonságokat tartalmaz. A tulajdonságok nyilvánosak, és get és set tartozékokat is tartalmaznak. A nyilvános tartozékokkal bármely objektum elolvashatja és megírhatja ezeket a tulajdonságokat.

Néha ki kell zárni az egyik tartozékot. Kihagyhatja a set tartozékot, hogy a tulajdonság írásvédett legyen:


public string Name
{
    get
    {
        return _name;
    }
}


Másik lehetőségként közzéteheti az egyik tartozékot nyilvánosan, de a másikat magánjellegűvé vagy védetté teheti.


public string Name
{
    get
    {
        return _name;
    }
    private set
    {
        _name = value;
    }
}