Objekte – Erstellen von Instanzen von Typen

Die Definition einer Klasse oder Struktur ist mit einem Entwurf vergleichbar, der angibt, was der Typ machen kann. Ein Objekt ist im Grunde ein Speicherblock, der nach Plan zugewiesen und konfiguriert wurde. Ein Programm kann viele Objekte der selben Klasse erstellen. Objekte werden auch Instanzen genannt, und sie können entweder in einer benannten Variable, einem Array oder in einer Auflistung gespeichert werden. Der Client-Code ist der Code, der diese Variablen verwendet, um die Methoden aufzurufen und um auf die öffentlichen Eigenschaften des Objekts zuzugreifen. In einer objektorientierten Programmiersprache wie C# besteht ein typisches Programm aus mehreren Objekten, die dynamisch interagieren.

Hinweis

Statische Typen verhalten sich anders, als die hier beschriebenen. Weitere Informationen finden Sie unter Statische Klassen und statische Klassenmember.

Strukturinstanzen im Vergleich zu Klasseninstanzen

Da Klassen Verweistypen sind, enthält eine Variable eines Klassenobjekts einen Verweis auf die Adresse des Objekts auf dem verwalteten Heap. Wenn der ersten Variable eine zweite Variable desselben Typs zugewiesen wird, verweisen beide Variablen auf das Objekt an dieser Adresse. Dieser Punkt wird weiter unten in diesem Artikel ausführlicher behandelt.

Instanzen von Klassen werden mit dem Operator new erstellt. Im folgenden Beispiel ist Person der Typ und person1 und person2 sind Instanzen oder Objekte des Typs.

using System;

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);
    }
}
/*
    Output:
    person1 Name = Leopold Age = 6
    person2 Name = Molly Age = 16
    person1 Name = Molly Age = 16
*/

Da Strukturen Werttypen sind, enthält eine Variable eines Strukturobjekts eine Kopie des gesamten Objekts. Instanzen von Strukturen können auch mithilfe des new-Operators erstellt werden; dies ist jedoch nicht erforderlich, wie im folgenden Beispiel gezeigt wird:

using System;

namespace Example
{
    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);
        }
    }
    /*
        Output:
        p1 Name = Alex Age = 9
        p2 Name = Spencer Age = 7
        p1 Name = Alex Age = 9
    */
}

Der Speicher für p1 und p2 ist dem Stapel des Threads zugeordnet. Dieser Arbeitsspeicher wird zusammen mit dem Typ oder der Methode freigegeben, in dem bzw. in der er deklariert ist. Dies ist ein Grund, weshalb Strukturen bei Zuweisung kopiert werden. Im Gegensatz dazu wird der Speicher, der für eine Klasseninstanz zugeordnet ist, automatisch von der Common Language Runtime freigegeben (von Garbage Collection bereinigt), wenn alle Verweise auf das Objekt außerhalb des Gültigkeitsbereichs liegen. Es ist nicht möglich, ein Klassenobjekt wie in C++ deterministisch zu zerstören. Weitere Informationen zur Garbage Collection in .NET finden Sie unter Garbage Collection.

Hinweis

Die Belegung und Freigabe von Arbeitsspeicher auf dem verwalteten Heap ist in der Common Language Runtime stark optimiert. In den meisten Fällen besteht kein wesentlicher Unterschied zwischen den Leistungskosten beim Zuweisen einer Klasseninstanz auf dem Heap im Vergleich zum Zuweisen einer Strukturinstanz im Stapel.

Objektidentität im Vergleich zur Wertgleichheit

Wenn Sie zwei Objekte auf Gleichheit vergleichen, müssen Sie zuerst unterscheiden, ob Sie wissen möchten, ob die zwei Variablen das gleiche Objekt im Speicher darstellen, oder ob die Werte von einem oder mehreren Feldern gleich sind. Wenn Sie planen, Werte zu vergleichen, müssen Sie berücksichtigen, ob die Objekte Instanzen von Werttypen (Strukturen) oder Verweistypen (Klassen, Delegate, Arrays) sind.

  • Verwenden Sie die statische Methode Object.Equals, um zu bestimmen, ob zwei Klasseninstanzen auf den gleichen Speicherort im Arbeitsspeicher verweisen (d.h., sie haben die gleiche Identität). (System.Object ist die implizite Basisklasse für alle Wert- und Referenztypen, einschließlich benutzerdefinierter Strukturen und Klassen.)

  • Verwenden Sie die Methode ValueType.Equals, um zu bestimmen, ob die Instanzfelder in zwei Strukturinstanzen die gleichen Werte haben. Da alle Strukturen implizit von System.ValueType erben, rufen Sie die Methode direkt an Ihrem Objekt auf, wie im folgenden Beispiel gezeigt wird:

    // Person is defined in the previous example.
    
    //public struct Person
    //{
    //    public string Name;
    //    public int Age;
    //    public Person(string name, int age)
    //    {
    //        Name = name;
    //        Age = age;
    //    }
    //}
    
    Person p1 = new Person("Wallace", 75);
    Person p2 = new Person("", 42);
    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 in einigen Fällen Boxing und Reflexion. Informationen zum Bereitstellen eines für Ihren Typ spezifischen effizienten Gleichheitsalgorithmus finden Sie unter Definieren von Wertgleichheit für einen Typ. Datensätze sind Verweistypen, die Wertsemantik für Gleichheit verwenden.

  • Sie können möglicherweise die Methode Equals oder den ==-Operator verwenden, um zu bestimmen, ob die Werte des Felds in zwei Klasseninstanzen gleich sind. Verwenden Sie sie jedoch nur, wenn die Klasse die Werte überschrieben oder überladen hat, um eine benutzerdefinierte Definition von „Gleichheit“ für Objekte dieses Typs bereitzustellen. Die Klasse kann auch die Schnittstelle IEquatable<T> oder die Schnittstelle IEqualityComparer<T> implementieren. Beide Schnittstellen bieten Methoden, die zum Testen der Wertgleichheit verwendet werden können. Wenn Sie Ihre eigenen Klassen entwickeln, die Equals überschreiben, achten Sie darauf, die Richtlinien zu befolgen, die in Vorgehensweise: Definieren von Wertgleichheit für einen Typ und Object.Equals(Object) aufgeführt sind.

Weitere Informationen finden Sie unter: