Objekte (C#-Programmierhandbuch)

Eine Klassen- oder Strukturdefinition ist mit einer Blaupause vergleichbar, die die Möglichkeiten des Typs angibt. Ein Objekt stellt im Wesentlichen einen Speicherblock dar, der auf Grundlage der Blaupause belegt und konfiguriert wurde. Von einem Programm können viele Objekte derselben Klasse erstellt werden. Objekte werden auch Instanzen genannt. Sie können in einer benannten Variablen, in einem Array oder in einer Auflistung gespeichert werden. Clientcode ist der Code, der diese Variablen verwendet, um die Methoden aufzurufen und auf die öffentlichen Eigenschaften des Objekts zuzugreifen. In einer objektorientierten Sprache, wie z. B. C#, besteht ein typisches Programm aus mehreren, dynamisch interagierenden Objekten.

Tipp

Statische Typen weisen ein anderes als das hier beschriebene Verhalten auf. Weitere Informationen finden Sie unter Statische Klassen und statische Klassenmember (C#-Programmierhandbuch).

Strukturinstanzen im Vergleich zuKlasseninstanzen

Da es sich bei Klassen um Referenztypen handelt, enthalten Variablen eines Klassenobjekts einen Verweis auf die Adresse des Objekts auf dem verwalteten Heap. Wenn dem ersten Objekt ein zweites Objekt desselben Typs zugewiesen wird, verweisen beide Variablen auf das Objekt an dieser Adresse. Dieser Punkt wird weiter unten in diesem Thema ausführlich erläutert.

Instanzen von Klassen werden mit dem Operator "new" erstellt. Im folgenden Beispiel stellt Person den Typ dar, und person1 und person 2 sind Instanzen bzw. Objekte dieses Typs.

public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
    public Person(string name, int age)
    {
        Name = name;
        Age = age;
    }
    //Other properties, methods, events...
}

class Program
{
    static void Main()
    {
        Person person1 = new Person("Leopold", 6);
        Console.WriteLine("person1 Name = {0} Age = {1}", person1.Name, person1.Age);

        // Declare  new person, assign person1 to it.
        Person person2 = person1;

        //Change the name of person2, and person1 also changes.
        person2.Name = "Molly";
        person2.Age = 16;

        Console.WriteLine("person2 Name = {0} Age = {1}", person2.Name, person2.Age);
        Console.WriteLine("person1 Name = {0} Age = {1}", person1.Name, person1.Age);

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

    }
}
/*
    Output:
    person1 Name = Leopold Age = 6
    person2 Name = Molly Age = 16
    person1 Name = Molly Age = 16
*/

Da es sich bei Strukturen um Werttypen handelt, enthält die Variable eines Strukturobjekts eine Kopie des gesamten Objekts. Strukturinstanzen können daher mithilfe des Operators new erstellt werden. Dies ist jedoch, wie im folgenden Beispiel dargestellt, nicht erforderlich:

public struct Person
{
    public string Name;
    public int Age;
    public Person(string name, int age)
    {
        Name = name;
        Age = age;
    }
}

public class Application
{
    static void Main()
    {
        // Create  struct instance and initialize by using "new".
        // Memory is allocated on thread stack.
        Person p1 = new Person("Alex", 9);
        Console.WriteLine("p1 Name = {0} Age = {1}", p1.Name, p1.Age);

        // Create  new struct object. Note that  struct can be initialized
        // without using "new".
        Person p2 = p1;

        // Assign values to p2 members.
        p2.Name = "Spencer";
        p2.Age = 7;
        Console.WriteLine("p2 Name = {0} Age = {1}", p2.Name, p2.Age);

        // p1 values remain unchanged because p2 is  copy.
        Console.WriteLine("p1 Name = {0} Age = {1}", p1.Name, p1.Age);

        // Keep the console open in debug mode.
        Console.WriteLine("Press any key to exit.");
        Console.ReadKey();
    }
}
/*
  Output:
    p1 Name = Alex Age = 9
    p2 Name = Spencer Age = 7
    p1 Name = Alex Age = 9
*/

Der Arbeitsspeicher wird sowohl für p1 als auch für p2 auf dem Threadstapel belegt. Dieser Arbeitsspeicher wird zusammen mit dem Typ oder der Methode wieder freigegeben, in dem bzw. der er deklariert ist. Dies ist ein Grund, weshalb Strukturen bei Zuweisung kopiert werden. Im Gegensatz dazu wird der für eine Klasseninstanz belegte Speicher automatisch von der Common Language Runtime freigegeben (mithilfe der Garbage Collection), wenn alle Verweise auf das Objekt ungültig geworden sind. Klassenobjekte können nicht deterministisch zerstört werden wie in C++. Weitere Informationen über Garbage Collection in .NET Framework finden Sie unter Garbage Collection.

Tipp

Das Belegen und das Freigeben von Speicher auf dem verwalteten Heap wurden in der Common Language Runtime stark optimiert. Meist besteht kein wesentlicher Unterschied zwischen den Leistungseinbußen bei der Reservierung einer Klasseninstanz auf dem Heap und dem Reservieren einer Strukturinstanz auf dem Stapel.

Objektidentität oderWertgleichheit

Wenn Sie zwei Objekte auf Gleichheit prüfen möchten, müssen Sie zunächst entscheiden, ob Sie prüfen möchten, ob die beiden Variablen dasselbe Objekt im Speicher darstellen oder ob die Werte für eines oder mehrere ihrer Felder übereinstimmen. Beim Vergleich von Werten muss beachtet werden, ob es sich bei den Objekten um Instanzen von Werttypen (Strukturen) oder Referenztypen (Klassen, Delegate oder Arrays) handelt.

  • Um zu ermitteln, ob zwei Klasseninstanzen auf denselben Speicherplatz verweisen (d. h., sie haben dieselbe Identität), können Sie die statische Equals-Methode verwenden. (System.Object stellt die implizite Basisklasse für alle Wert- und Referenztypen, einschließlich benutzerdefinierter Strukturen und Klassen, dar.)

  • Mit der ValueType.Equals-Methode können Sie bestimmen, ob die Instanzfelder zweier Strukturinstanzen über dieselben Werte verfügen. Da alle Strukturen implizit von System.ValueType erben, wird die Methode für das Objekt direkt aufgerufen, wie im folgenden Beispiel gezeigt:

Person p1 = new Person("Wallace", 75);
Person p2;
p2.Name = "Wallace";
p2.Age = 75;

if (p2.Equals(p1))
    Console.WriteLine("p2 and p1 have the same values.");

// Output: p2 and p1 have the same values.

Die System.ValueType-Implementierung von Equals verwendet Reflektion, da sie die Typen der Felder jeder Struktur ermitteln muss. Wenn Sie eigene Strukturen erstellen, überschreiben Sie die Equals-Methode, um einen effizienten, auf den von Ihnen verwendeten Typ zugeschnittenen Algorithmus zur Prüfung auf Gleichheit bereitzustellen.

  • Um zu bestimmen, ob die Werte der Felder in zwei Klasseninstanzen gleich sind, können Sie die Equals-Methode oder den Operator == verwenden. Nutzen Sie sie jedoch nur dann, wenn die Klasse sie überschrieben oder überladen hat, um eine benutzerdefinierte Definition dafür bereitzustellen, was "Gleichheit" für Objekte dieses Typs bedeutet. Die Klasse kann auch die IEquatable<T>-Schnittstelle oder die IEqualityComparer<T>-Schnittstelle implementieren. Beide Schnittstellen stellen Methoden bereit, mit denen die Wertgleichheit getestet werden kann. Wenn Sie eigene Klassen entwerfen, die Equals überschreiben, stellen Sie sicher, dass Sie die Richtlinien befolgen, die in Gewusst wie: Definieren von Wertgleichheit für einen Typ (C#-Programmierhandbuch) und Object.Equals(Object) angegeben sind.

Verwandte Abschnitte

Weitere Informationen:

Siehe auch

Referenz

object (C#-Referenz)

Vererbung (C#-Programmierhandbuch)

class (C#-Referenz)

struct (C#-Referenz)

new-Operator (C#-Referenz)

Konzepte

C#-Programmierhandbuch

Allgemeines Typsystem