Verwenden von Eigenschaften (C#-Programmierhandbuch)

Eigenschaften kombinieren Aspekte der Felder und der Methoden. Für den Benutzer eines Objekts erscheint eine Eigenschaft wie ein Feld; 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 den get-Accessor wird ausgeführt, wenn die Eigenschaft gelesen wird; der Codeblock für den set-Accessor wird ausgeführt, wenn der Eigenschaft ein neuer 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.

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 in Wirklichkeit 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
        {
            return 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 für eine Eigenschaft wird häufig als „Sicherungsspeicher“ der Eigenschaft bezeichnet. Es ist üblich für Eigenschaften, die privaten Felder als Sicherungsspeicher zu 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.

Der get-Accessor

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 vom get -Accessor zurückgeben und Optimierungen aktiviert sind, wird der Aufruf an die get-Accessor-Methode vom Compiler eingebettet, damit kein zusätzlicher Aufwand an Methodenaufrufen entsteht. Allerdings kann eine get-Accessor-Methode kann nicht eingebettet werden, da der Compiler zum Zeitpunkt der Kompilierung nicht erkennt, welche Methode zur Laufzeit tatsächlich aufgerufen wird. Im folgenden finden Sie einen get-Accessor, der den Wert eines privaten Felds zurückgibt name:

class Person
{
    private string name;  // the name field
    public string Name    // the Name property
    {
        get
        {
            return name;
        }
    }
}

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:

Person person = new Person();
//...

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

Der get Accessor muss mit einer return- oder einer throw-Anweisung enden, und die Steuerung darf nicht über den Accessortext hinausgehen.

Es ist ein unzulässiger Programmierstil den Zustand des Objekts mithilfe des get-Accessors zu verändern. Der folgende Accessor hat z.B. den Nebeneffekt, dass der Zustand des Objekts, bei jedem Zugriff auf das number-Feld verändert wird.

private int number;
public int Number
{
    get
    {
        return number++;   // Don't do this
    }
}

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 Employee
{
    private string name;
    public string Name
    {
        get
        {
            return name != null ? name : "NA";
        }
    }
}

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

Der set-Accessor

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 Person
{
    private string name;  // the name field
    public string Name    // the Name property
    {
        get
        {
            return 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:

Person person = new Person();
person.Name = "Joe";  // the set accessor is invoked here                

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

Das Verwenden des impliziten Parameternamens, value, für die Deklaration einer lokalen Variablen in einem set-Accessor ist ein Fehler.

Hinweise

Eigenschaften können gekennzeichnet werden, als public, private, protected, internal, oder protected internal. 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. Dadurch steht das Feld 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. Dies ermöglicht abgeleiteten Klassen, das Ereignisverhalten mithilfe des override-Schlüsselworts zu überschreiben. Weitere Informationen zu diesen Optionen finden Sie unter Vererbung.

Ein Ereignis, das ein virtuelles Ereignis überschreibt, kann auch sealed(verschlossen) sein, was angibt, dass es für abgeleitete Klassen nicht mehr virtuell ist. Schließlich kann eine Eigenschaft als abstract(abstrakt) deklariert werden. Dies bedeutet, dass es keine Implementierung in der Klasse gibt, und abgeleitete Klassen müssen eine eigene Implementierung schreiben. 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.

Beispiel

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 { return name; }
        set { name = value; }
    }

    // A read-only static property:
    public static int Counter
    {
        get { return counter; }
    }

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

class TestEmployee
{
    static void Main()
    {
        Employee.NumberOfEmployees = 107;
        Employee e1 = new Employee();
        e1.Name = "Claude Vige";

        System.Console.WriteLine("Employee number: {0}", Employee.Counter);
        System.Console.WriteLine("Employee name: {0}", e1.Name);
    }
}
/* Output:
    Employee number: 108
    Employee name: Claude Vige
*/

Beispiel

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 { return name; }
        set { name = value; }
    }
}

public class Manager : Employee
{
    private string name;

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

class TestHiding
{
    static void Main()
    {
        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

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;

    public Square(double s)  //constructor
    {
        side = s;
    }

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

class Cube : Shape
{
    public double side;

    public Cube(double s)
    {
        side = s;
    }

    public override double Area
    {
        get
        {
            return 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

C#-Programmierhandbuch
Eigenschaften
Schnittstelleneigenschaften
Automatisch implementierte Eigenschaften