Verwenden von Eigenschaften (C#-Programmierhandbuch)

Eigenschaften kombinieren Aspekte der Felder und der Methoden. Für Benutzer*innen eines Objekts scheint eine Eigenschaft ein Feld zu sein; der Zugriff auf die Eigenschaft erfordert dieselbe Syntax. Für den Implementierer einer Klasse, besteht eine Eigenschaft aus einem oder zwei Codeblöcken, die einen get-Accessor und/oder einen set-Accessor darstellen. Der Codeblock für die get-Zugriffsmethode wird ausgeführt, wenn die Eigenschaft gelesen wird; der Codeblock für die set-Zugriffsmethode wird ausgeführt, wenn der Eigenschaft ein Wert zugewiesen wird. Eine Eigenschaft ohne einen set-Accessor ist schreibgeschützt. Eine Eigenschaft ohne einen get-Accessor ist lesegeschützt. Eine Eigenschaft, die beide Accessoren umfasst, ermöglicht Lese-/ Schreibzugriff. Sie können eine init-Zugriffsmethode anstelle einer set-Zugriffsmethode verwenden, um die Eigenschaft als schreibgeschützt zu kennzeichnen.

Im Gegensatz zu Feldern, werden Eigenschaften nicht als Variablen klassifiziert. Aus diesem Grund können Sie Eigenschaften nicht als ref oder out-Parameter übergeben.

Eigenschaften sind vielseitig verwendbar: Sie können Daten überprüfen, bevor sie eine Änderung zulassen. Sie können Daten in einer Klasse transparent verfügbar machen, in denen die Daten von einer anderen Quelle abgerufen werden, z.B. einer Datenbank. Sie können eine Aktion ausführen, wenn Daten geändert werden, z.B. ein Ereignis auslösen, oder den Wert anderer Felder verändern.

Eigenschaften werden im Klassenblock deklariert, indem die Zugriffsebene des Felds angegeben wird, gefolgt vom Typ der Eigenschaft, gefolgt vom Namen der Eigenschaft und gefolgt von einem Codeblock, der einen get-Accessor und/oder einen set Accessor deklariert. Zum Beispiel:

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

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

In diesem Beispiel wird Month als Eigenschaft so deklariert, dass der set-Accessor dafür sorgen kann, dass der Month-Wert zwischen 1 und 12 festgelegt wird. Die Month-Eigenschaft verwendet ein privates Feld, um den tatsächlichen Wert nachzuverfolgen. Der tatsächliche Speicherort der Daten einer Eigenschaft wird häufig als „Sicherungsspeicher“ der Eigenschaft bezeichnet. Es ist üblich, dass Eigenschaften private Felder als Sicherungsspeicher verwenden. Das Feld wird als privat gekennzeichnet um sicherzustellen, dass es nur durch Aufrufen der Eigenschaft geändert werden kann. Weitere Informationen zu öffentlichen und privaten Zugriffsbeschränkungen finden Sie unter Zugriffsmodifizierer.

Automatisch implementierte Eigenschaften stellen eine vereinfachte Syntax für einfache Eigenschaftendeklarationen bereit. Weitere Informationen finden Sie unter Automatisch implementierte Eigenschaften.

Die get-Zugriffsmethode

Der Text des get Accessors ähnelt dem einer Methode. Er muss einen Wert des Eigenschaftentyps zurückgeben. Die Ausführung des get Accessors entspricht dem Lesen des Wert des Felds. Wenn Sie z. B. die private Variable von der get-Zugriffsmethode zurückgeben und Optimierungen aktiviert sind, wird der Aufruf an die get-Zugriffsmethode vom Compiler eingebettet, damit kein zusätzlicher Aufwand an Methodenaufrufen entsteht. Allerdings kann eine virtuelle get-Zugriffsmethode nicht eingebettet werden, da der Compiler zum Zeitpunkt der Kompilierung nicht weiß, welche Methode zur Laufzeit tatsächlich aufgerufen wird. Das folgende Beispiel veranschaulicht eine get-Zugriffsmethode, die den Wert eines privaten Felds (_name) zurückgibt:

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

Wenn Sie auf die Eigenschaft, außer als Ziel einer Zuweisung, verweisen, wird der get-Accessor aufgerufen, um den Wert der Eigenschaft zu lesen. Zum Beispiel:

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

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

Die get-Zugriffsmethode muss mit einer return- oder einer throw-Anweisung enden, und die Steuerung darf nicht über den Text der Zugriffsmethode hinausgehen.

Warnung

Es ist kein guter Programmierstil, den Zustand des Objekts mithilfe der get-Zugriffsmethode zu verändern.

Der get-Accessor kann verwendet werden, um den Wert des Felds zurückzugeben, oder um den Wert des Felds zu berechnen und zurückgeben. Zum Beispiel:

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

Im obigen Codesegment wird der Wert NA zurückgegeben, wenn Sie der Name-Eigenschaft keinen Wert zuweisen.

Die set-Zugriffsmethode

Der set-Accessor ähnelt einer Methode, deren Rückgabetyp void ist. Er verwendet einen impliziten Parameter mit dem Namen value, dessen Typ der Typ der Eigenschaft ist. Im folgenden Beispiel wird ein set-Accessor der Name-Eigenschaft hinzugefügt.

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

Wenn Sie der Eigenschaft einen Wert zuweisen, wird der set-Accessor mit einem Argument aufgerufen, das den neuen Wert bereitstellt. Zum Beispiel:

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

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

Das Verwenden des impliziten Parameternamens, value, für die Deklaration einer lokalen Variablen in einer set-Zugriffsmethode führt zu einem Fehler.

Die init-Zugriffsmethode

Der Code zum Erstellen einer init-Zugriffsmethode ist derselbe wie der Code zum Erstellen einer set-Zugriffsmethode, mit der Ausnahme, dass Sie das Schlüsselwort init anstelle von set verwenden. Der Unterschied besteht darin, dass die init-Zugriffsmethode nur im Konstruktor oder mithilfe eines Objektinitialisierers verwendet werden kann.

Hinweise

Eigenschaften können als public, private, protected, internal, protected internal oder private protected gekennzeichnet werden. Diese Zugriffsmodifizierer definieren, wie Benutzer der Klasse auf die Eigenschaft zugreifen können. Die get- und set-Accessoren für die gleiche Eigenschaft haben möglicherweise verschiedene Zugriffsmodifizierer. Z.B. kann get möglicherweise public sein, um den schreibgeschützten Zugriff von außerhalb des Typs zu ermöglichen, und set kann möglicherweise private oder protected sein. Weitere Informationen finden Sie unter Zugriffsmodifizierer.

Eine Eigenschaft kann als statische Eigenschaft deklariert werden, mithilfe des static-Schlüsselworts. Statische Eigenschaften stehen Aufrufern jederzeit zur Verfügung, auch wenn keine Instanz der Klasse vorhanden ist. Weitere Informationen finden Sie unter Statische Klassen und statische Klassenmember.

Ein Ereignis kann mithilfe des virtual-Schlüsselworts als virtuelles Ereignis gekennzeichnet werden. Virtuelle Eigenschaften ermöglichen es abgeleiteten Klassen, das Ereignisverhalten mit dem override-Schlüsselwort zu überschreiben. Weitere Informationen zu diesen Optionen finden Sie unter Vererbung.

Eine Eigenschaft, die eine virtuelle Eigenschaft überschreibt, kann auch versiegelt (sealed) werden, um anzugeben, dass sie für abgeleitete Klassen nicht mehr virtuell ist. Schließlich kann eine Eigenschaft als abstract(abstrakt) deklariert werden. Abstrakte Eigenschaften definieren keine Implementierung in der Klasse, sodass für abgeleitete Klassen eine eigene Implementierung geschrieben werden muss. Weitere Informationen zu abstrakten Klassen finden Sie unter Abstrakte und versiegelte Klassen und Klassenmember.

Hinweis

Das Verwenden eines virtual(virtuell)-, abstract(abstrakt)- oder override(außer Kraft setzen)- Modifizierers für einen Accessor einer statischen Eigenschaft ist ein Fehler.

Beispiele

Dieses Beispiel zeigt,Instanz-, statische- und schreibgeschützte Eigenschaften. Dieser Parameter akzeptiert den Namen des Mitarbeiters auf der Tastatur, Inkremente NumberOfEmployees durch 1, und zeigt den Mitarbeiternamen und die Nummer an.

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

Beispiel für eine ausgeblendete Eigenschaft

In diesem Beispiel wird veranschaulicht, wie auf eine Eigenschaft in einer Basisklasse zugegriffen werden kann, die von einer anderen Eigenschaft ausgeblendet ist, die in einer abgeleiteten Klasse den gleichen Namen hat:

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

Die folgenden Punkte im vorherigen Beispiel sind wichtig:

  • Die Eigenschaft Name in der abgeleiteten Klasse blendet die Eigenschaft Name in der Basisklasse aus. In solch einem Fall wird der new-Modifizierer in der Deklaration der Eigenschaft in der abgeleiteten Klasse verwendet:
    public new string Name
    
  • Die Umwandlung (Employee) wird für den Zugriff auf die ausgeblendete Eigenschaft in der Basisklasse verwendet:
    ((Employee)m1).Name = "Mary";
    

Weitere Informationen zum Ausblenden von Mitgliedern finden Sie unter new-Modifizierer.

Beispiel für Überschreibungseigenschaft

In diesem Beispiel implementieren zwei Klassen Cube und Square eine abstrakte Klasse Shape, und überschreiben die abstrakte Area-Eigenschaft. Beachten Sie die Verwendung des überschreiben-Modifizierers in den Eigenschaften. Das Programm akzeptiert die Seite als Eingabe und berechnet die Bereiche für das Quadrat und den Cube. Das Programm akzeptiert auch den Bereich als Eingabe und berechnet die entsprechende Seite für das Quadrat und den Cube.

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

Siehe auch