Share via


Använda egenskaper (C#-programmeringsguide)

Egenskaper kombinerar aspekter av både fält och metoder. För användaren av ett objekt verkar en egenskap vara ett fält. Åtkomst till egenskapen kräver samma syntax. För implementeraren för en klass är en egenskap ett eller två kodblock som representerar en get accessor och/eller en eller init en set accessor. Kodblocket get för accessorn körs när egenskapen läss. Kodblocket för set eller-accessorn init körs när egenskapen tilldelas ett värde. En egenskap utan set åtkomst anses vara skrivskyddad. En egenskap utan en get accessor betraktas som skrivskyddad. En egenskap som har båda åtkomsterna är skrivskyddad. Du kan använda en init accessor i stället för en set accessor för att aktivera att egenskapen anges som en del av objektinitiering, men annars göra den skrivskyddad.

Till skillnad från fält klassificeras inte egenskaper som variabler. Därför kan du inte skicka en egenskap som en ref eller out -parameter.

Egenskaper har många användningsområden:

  • De kan verifiera data innan de tillåter en ändring.
  • De kan transparent exponera data i en klass där dessa data hämtas från någon annan källa, till exempel en databas.
  • De kan vidta en åtgärd när data ändras, till exempel att skapa en händelse eller ändra värdet för andra fält.

Egenskaper deklareras i klassblocket genom att ange åtkomstnivån för fältet, följt av egenskapens typ, följt av namnet på egenskapen och följt av ett kodblock som deklarerar en get-accessor och/eller en set accessor. Till exempel:

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

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

I det här exemplet Month deklareras som en egenskap så att set användaren kan se till att Month värdet anges mellan 1 och 12. Egenskapen Month använder ett privat fält för att spåra det faktiska värdet. Den verkliga platsen för en egenskaps data kallas ofta för egenskapens "backningslager". Det är vanligt att egenskaper använder privata fält som ett lagringsarkiv. Fältet är markerat som privat för att se till att det bara kan ändras genom att anropa egenskapen. Mer information om begränsningar för offentlig och privat åtkomst finns i Åtkomstmodifierare. Auto-implementerade egenskaper ger förenklad syntax för enkla egenskapsdeklarationer. Mer information finns i Auto-Implemented Properties (Automatiskt implementerade egenskaper).

Hämta-accessorn

Accessorns get brödtext liknar den för en metod. Det måste returnera ett värde av egenskapstypen. Kompilatorn C#-kompilatorn och JIT-kompilatorn (Just-in-time) identifierar vanliga mönster för att implementera get accessorn och optimerar dessa mönster. Till exempel optimeras en get accessor som returnerar ett fält utan att utföra någon beräkning till en minnesläsning av det fältet. Automatiskt implementerade egenskaper följer det här mönstret och drar nytta av dessa optimeringar. Det går dock inte att infoga en virtuell get accessor-metod eftersom kompilatorn inte vet vid kompileringstillfället vilken metod som faktiskt kan anropas vid körning. I följande exempel visas en get accessor som returnerar värdet för ett privat fält _name:

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

När du refererar till egenskapen, förutom som mål för en tilldelning, get anropas accessorn för att läsa värdet för egenskapen. Till exempel:

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

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

Accessorn get måste vara en uttryckskroppsmedlem, eller sluta i en retur - eller throw-instruktion , och kontrollen kan inte flöda från accessor-brödtexten.

Varning

Det är ett felaktigt programmeringsformat för att ändra objektets tillstånd med hjälp get av accessorn.

Accessorn get kan användas för att returnera fältvärdet eller för att beräkna det och returnera det. Till exempel:

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

Om du inte tilldelar egenskapen något värde Name i föregående exempel returneras värdet NA.

Set-åtkomstorn

Accessorn set liknar en metod vars returtyp är tom. Den använder en implicit parameter med namnet value, vars typ är egenskapens typ. Kompilatorn och JIT-kompilatorn känner också igen vanliga mönster för en eller init en set accessor. Dessa vanliga mönster är optimerade och skriver direkt minnet för bakgrundsfältet. I följande exempel läggs en set accessor till i egenskapen Name :

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

När du tilldelar egenskapen ett värde set anropas accessorn med hjälp av ett argument som ger det nya värdet. Till exempel:

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

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

Det är ett fel att använda det implicita parameternamnet , valueför en lokal variabeldeklaration i en set accessor.

Init-åtkomstorn

Koden för att skapa en init accessor är samma som koden för att skapa en set accessor förutom att du använder nyckelordet init i stället för set. Skillnaden är att init accessorn endast kan användas i konstruktorn eller med hjälp av en objektinitierare.

Kommentarer

Egenskaper kan markeras som public, private, protected, internal, protected internaleller private protected. Dessa åtkomstmodifierare definierar hur användare av klassen kan komma åt egenskapen. Accessorerna get och set för samma egenskap kan ha olika åtkomstmodifierare. Till exempel get kan vara public att tillåta skrivskyddad åtkomst utanför typen och set kan vara private eller protected. Mer information finns i Åtkomstmodifierare.

En egenskap kan deklareras som en statisk egenskap med hjälp av nyckelordet static . Statiska egenskaper är tillgängliga för anropare när som helst, även om det inte finns någon instans av klassen. Mer information finns i Statiska klasser och Statiska klassmedlemmar.

En egenskap kan markeras som en virtuell egenskap med hjälp av det virtuella nyckelordet. Med virtuella egenskaper kan härledda klasser åsidosätta egenskapsbeteendet med hjälp av nyckelordet åsidosättning . Mer information om dessa alternativ finns i Arv.

En egenskap som åsidosätter en virtuell egenskap kan också förseglas och ange att den inte längre är virtuell för härledda klasser. Slutligen kan en egenskap förklaras abstrakt. Abstrakta egenskaper definierar inte någon implementering i klassen, och härledda klasser måste skriva sin egen implementering. Mer information om dessa alternativ finns i Abstrakta och förseglade klasser och klassmedlemmar.

Kommentar

Det är ett fel att använda en virtuell, abstrakt eller åsidosättningsmodifierare på en accessor för en statisk egenskap.

Exempel

Det här exemplet visar egenskaper för instanser, statiska och skrivskyddade. Den accepterar namnet på medarbetaren från tangentbordet, ökar med NumberOfEmployees 1 och visar medarbetarens namn och nummer.

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

Exempel på dold egenskap

Det här exemplet visar hur du får åtkomst till en egenskap i en basklass som är dold av en annan egenskap som har samma namn i en härledd klass:

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
*/

Följande är viktiga punkter i föregående exempel:

  • Egenskapen Name i den härledda klassen döljer egenskapen Name i basklassen. I sådana fall new används modifieraren i deklarationen av egenskapen i den härledda klassen:
    public new string Name
    
  • Gjutningen (Employee) används för att komma åt den dolda egenskapen i basklassen:
    ((Employee)m1).Name = "Mary";
    

Mer information om hur du döljer medlemmar finns i den nya modifieraren.

Exempel på åsidosättningsegenskap

I det här exemplet implementerar två klasser, Cube och Square, en abstrakt klass, Shapeoch åsidosätter dess abstrakta Area egenskap. Observera användningen av åsidosättningsmodifieraren för egenskaperna. Programmet accepterar sidan som indata och beräknar områdena för kvadraten och kuben. Den accepterar också området som indata och beräknar motsvarande sida för kvadraten och kuben.

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
*/

Se även