Megosztás a következőn keresztül:


Tulajdonságok használata (C# programozási útmutató)

A tulajdonságok a mezők és a metódusok aspektusait egyesítik. Egy objektum felhasználója számára egy tulajdonság mezőnek tűnik; A tulajdonság eléréséhez ugyanaz a szintaxis szükséges. Az osztály megvalósítójának egy tulajdonság egy vagy két kódblokk, amely egy get tartozékot és/vagy tartozékot set init jelöl. A tartozék kódblokkját a get rendszer a tulajdonság beolvasásakor hajtja végre; a kódblokk set a init tulajdonság értékhez való hozzárendelésekor lesz végrehajtva. A tartozék nélküli set tulajdonságok írásvédettnek minősülnek. A tartozék nélküli get tulajdonságok írásvédettnek minősülnek. A mindkét tartozékot tartalmazó tulajdonság írás-olvasás. Tartozék helyett set kiegészítővel init engedélyezheti, hogy a tulajdonság az objektum inicializálásának részeként legyen beállítva, de máskülönben írásvédetté teheti.

A mezőkkel ellentétben a tulajdonságok nem tartoznak változók közé. Ezért nem adhat át tulajdonságot paraméterként vagy out paraméterkéntref.

A tulajdonságoknak számos felhasználási módja van:

  • A módosítás engedélyezése előtt ellenőrizhetik az adatokat.
  • Transzparensen elérhetővé tehetik az adatokat egy olyan osztályon, ahol az adatokat más forrásból, például egy adatbázisból kérik le.
  • Az adatok módosításakor műveletet hajthatnak végre, például eseményt emelhetnek ki, vagy módosíthatják más mezők értékét.

A tulajdonságok az osztályblokkban deklarálhatók a mező hozzáférési szintjének megadásával, majd a tulajdonság típusával, majd a tulajdonság nevével, majd egy kódblokkgal, amely -accessort és/vagy tartozékot set deklarálget. Példa:

public class Date
{
    private int _month = 7;  // Backing store

    public int Month
    {
        get => _month;
        set
        {
            if ((value > 0) && (value < 13))
            {
                _month = value;
            }
        }
    }
}

Ebben a példában tulajdonságként van deklarálva, Month így a set tartozék meggyőződhet arról, hogy az Month érték 1 és 12 között van beállítva. A Month tulajdonság egy privát mezőt használ a tényleges érték nyomon követéséhez. A tulajdonság adatainak valós helyét gyakran nevezik a tulajdonság "háttértárának". Gyakran előfordul, hogy a tulajdonságok háttértárként privát mezőket használnak. A mező privátként van megjelölve, így csak a tulajdonság meghívásával módosítható. A nyilvános és a privát hozzáférés korlátozásairól további információt az Access-módosítók című témakörben talál. Az automatikusan implementált tulajdonságok egyszerűsített szintaxist biztosítanak az egyszerű tulajdonságdeklarációkhoz. További információ: Automatikusan implementált tulajdonságok.

A lekéréses tartozék

A tartozék teste get hasonlít egy módszerhez. A tulajdonságtípus értékét kell visszaadnia. A C# fordító és a just-in-time (JIT) fordító észleli a kiegészítő implementálásának gyakori mintáit, és optimalizálja ezeket a get mintákat. Például egy get olyan tartozék, amely számítás nélkül ad vissza egy mezőt, valószínűleg az adott mező memóriájába van optimalizálva. Az automatikusan mplemented tulajdonságok követik ezt a mintát, és kihasználják ezeket az optimalizálásokat. A virtuális get kiegészítő metódusok azonban nem ágyazhatók be, mert a fordító nem tudja a fordításkor, hogy melyik metódus hívható meg futásidőben. Az alábbi példa egy olyan kiegészítőt get mutat be, amely egy magánmező _nameértékét adja vissza:

    class Employee
{
    private string _name;  // the name field
    public string Name => _name;     // the Name property
}

Ha a tulajdonságra hivatkozik, kivéve a hozzárendelés célját, a rendszer meghívja a get tartozékot a tulajdonság értékének olvasásához. Példa:

var employee= new Employee();
//...

System.Console.Write(employee.Name);  // the get accessor is invoked here

A get tartozéknak kifejezési testű tagnak kell lennie, vagy visszatérési vagy dobási utasítással kell végződnie, és a vezérlő nem tud áramlani a tartozék törzsén.

Figyelmeztetés

Rossz programozási stílus az objektum állapotának módosítása a get tartozék használatával.

A get tartozék használható a mező értékének visszaadására vagy kiszámítására és visszaadására. Példa:

class Manager
{
    private string _name;
    public string Name => _name != null ? _name : "NA";
}

Az előző példában, ha nem rendel hozzá értéket a Name tulajdonsághoz, az az értéket NAadja vissza.

A készlet tartozéka

A set tartozék hasonlít egy olyan metódusra, amelynek visszatérési típusa érvénytelen. Implicit paramétert valuehasznál, amelynek típusa a tulajdonság típusa. A fordító és a JIT-fordító is felismeri egy vagy init több tartozék gyakori mintáitset. Ezek a gyakori minták optimalizálva vannak, közvetlenül a háttérmező memóriájának megírásával. Az alábbi példában egy set kiegészítőt adunk hozzá a Name tulajdonsághoz:

class Student
{
    private string _name;  // the name field
    public string Name    // the Name property
    {
        get => _name;
        set => _name = value;
    }
}

Amikor értéket rendel a tulajdonsághoz, a rendszer meghívja a set kiegészítőt egy argumentum használatával, amely az új értéket adja meg. Példa:

var student = new Student();
student.Name = "Joe";  // the set accessor is invoked here

System.Console.Write(student.Name);  // the get accessor is invoked here

Hiba az implicit paraméternév valuehasználata egy helyi változódeklarációhoz egy set tartozékban.

Az init tartozék

A kiegészítő létrehozásához init használt kód megegyezik a kiegészítő létrehozásához használt set kóddal, azzal a kivételével, hogy a kulcsszót használja ahelyettset, hogy a init . A különbség az, hogy a init tartozék csak a konstruktorban vagy egy objektum-inicializáló használatával használható.

Megjegyzések

A tulajdonságok megjelölhetők public, private, protected, internalprotected internalvagy private protected. Ezek a hozzáférési módosítók határozzák meg, hogy az osztály felhasználói hogyan férhetnek hozzá a tulajdonsághoz. Ugyanahhoz get a tulajdonsághoz és set tartozékaihoz különböző hozzáférési módosítók tartozhatnak. Lehetséges például, get public hogy a típuson kívülről engedélyezi az írásvédett hozzáférést, és az set lehet private vagy protected. További információ: Access Modifiers.

A tulajdonság a kulcsszó használatával static deklarálható statikus tulajdonságként. A statikus tulajdonságok bármikor elérhetők a hívók számára, még akkor is, ha az osztálynak nincs példánya. További információ: Statikus osztályok és statikus osztálytagok.

A tulajdonság a virtuális kulcsszóval jelölhető meg virtuális tulajdonságként. A virtuális tulajdonságok lehetővé teszik a származtatott osztályok számára, hogy felülbírálják a tulajdonság viselkedését a felülbírálási kulcsszó használatával. További információ ezekről a lehetőségekről: Öröklés.

A virtuális tulajdonságot felülíró tulajdonság is lezárható, megadva, hogy származtatott osztályok esetén már nem virtuális. Végül egy tulajdonság absztraktként is deklarálható. Az absztrakt tulajdonságok nem definiálnak implementációt az osztályban, a származtatott osztályoknak pedig saját implementációt kell írniuk. További információ ezekről a lehetőségekről: Absztrakt és lezárt osztályok és osztálytagok.

Feljegyzés

Hiba virtuális, absztrakt vagy felülbírálási módosító használata statikus tulajdonság tartozékán.

Példák

Ez a példa a példányok, a statikus és az írásvédett tulajdonságokat mutatja be. Elfogadja az alkalmazott nevét a billentyűzetről, 1-zel növekszik NumberOfEmployees , és megjeleníti az alkalmazott nevét és számát.

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:
}

Példa rejtett tulajdonságra

Ez a példa bemutatja, hogyan érhet el egy olyan tulajdonságot egy alaposztályban, amelyet egy másik, azonos nevű tulajdonság rejt el egy származtatott osztályban:

public class Employee
{
    private string _name;
    public string Name
    {
        get => _name;
        set => _name = value;
    }
}

public class Manager : Employee
{
    private string _name;

    // Notice the use of the new modifier:
    public new string Name
    {
        get => _name;
        set => _name = value + ", Manager";
    }
}

class TestHiding
{
    public static void Test()
    {
        Manager m1 = new Manager();

        // Derived class property.
        m1.Name = "John";

        // Base class property.
        ((Employee)m1).Name = "Mary";

        System.Console.WriteLine("Name in the derived class is: {0}", m1.Name);
        System.Console.WriteLine("Name in the base class is: {0}", ((Employee)m1).Name);
    }
}
/* Output:
    Name in the derived class is: John, Manager
    Name in the base class is: Mary
*/

Az előző példában a következő fontos pontok szerepelnek:

  • A származtatott osztály tulajdonsága Name elrejti a tulajdonságot Name az alaposztályban. Ilyen esetben a módosító a new származtatott osztályban lévő tulajdonság deklarációjában használatos:
    public new string Name
    
  • A bedobás (Employee) az alaposztály rejtett tulajdonságának elérésére szolgál:
    ((Employee)m1).Name = "Mary";
    

A tagok elrejtésével kapcsolatos további információkért tekintse meg az új módosítót.

Példa a tulajdonság felülbírálására

Ebben a példában két osztály és Cube Squareegy absztrakt osztály implementálása, Shapevalamint az absztrakt Area tulajdonság felülbírálása. Figyelje meg a felülbírálás módosítójának használatát a tulajdonságokon. A program bemenetként elfogadja az oldalt, és kiszámítja a négyzet és a kocka területeit. Bemenetként is elfogadja a területet, és kiszámítja a négyzet és a kocka megfelelő oldalát.

abstract class Shape
{
    public abstract double Area
    {
        get;
        set;
    }
}

class Square : Shape
{
    public double side;

    //constructor
    public Square(double s) => side = s;

    public override double Area
    {
        get => side * side;
        set => side = System.Math.Sqrt(value);
    }
}

class Cube : Shape
{
    public double side;

    //constructor
    public Cube(double s) => side = s;

    public override double Area
    {
        get => 6 * side * side;
        set => side = System.Math.Sqrt(value / 6);
    }
}

class TestShapes
{
    static void Main()
    {
        // Input the side:
        System.Console.Write("Enter the side: ");
        double side = double.Parse(System.Console.ReadLine());

        // Compute the areas:
        Square s = new Square(side);
        Cube c = new Cube(side);

        // Display the results:
        System.Console.WriteLine("Area of the square = {0:F2}", s.Area);
        System.Console.WriteLine("Area of the cube = {0:F2}", c.Area);
        System.Console.WriteLine();

        // Input the area:
        System.Console.Write("Enter the area: ");
        double area = double.Parse(System.Console.ReadLine());

        // Compute the sides:
        s.Area = area;
        c.Area = area;

        // Display the results:
        System.Console.WriteLine("Side of the square = {0:F2}", s.side);
        System.Console.WriteLine("Side of the cube = {0:F2}", c.side);
    }
}
/* Example Output:
    Enter the side: 4
    Area of the square = 16.00
    Area of the cube = 96.00

    Enter the area: 24
    Side of the square = 4.90
    Side of the cube = 2.00
*/

Lásd még