Udostępnij za pośrednictwem


Obiekty — tworzenie wystąpień typów

Definicja klasy lub struktury przypomina strategię określającą, co może zrobić typ. Obiekt jest w zasadzie blokiem pamięci, który został przydzielony i skonfigurowany zgodnie z strategią. Program może utworzyć wiele obiektów tej samej klasy. Obiekty są również nazywane wystąpieniami i mogą być przechowywane w nazwanej zmiennej lub w tablicy lub kolekcji. Kod klienta to kod, który używa tych zmiennych do wywoływania metod i uzyskiwania dostępu do publicznych właściwości obiektu. W języku obiektowym, takim jak C#, typowy program składa się z wielu obiektów współdziałających dynamicznie.

Uwaga

Typy statyczne zachowują się inaczej niż opisane tutaj. Aby uzyskać więcej informacji, zobacz Klasy statyczne i składowe klas statycznych.

Wystąpienia struktury a wystąpienia klas

Ponieważ klasy są typami referencyjnymi, zmienna obiektu klasy przechowuje odwołanie do adresu obiektu na zarządzanym stercie. Jeśli druga zmienna tego samego typu jest przypisana do pierwszej zmiennej, obie zmienne odwołują się do obiektu pod tym adresem. Ten punkt został omówiony bardziej szczegółowo w dalszej części tego artykułu.

Wystąpienia klas są tworzone przy użyciu new operatora . W poniższym przykładzie Person jest to typ i person1 person2 są wystąpieniami lub obiektami tego typu.

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

Ponieważ struktury są typami wartości, zmienna obiektu struktury przechowuje kopię całego obiektu. Wystąpienia struktur można również utworzyć przy użyciu new operatora , ale nie jest to wymagane, jak pokazano w poniższym przykładzie:

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

Pamięć dla obu p1 elementów i p2 jest przydzielana na stos wątku. Pamięć ta jest odzyskiwane wraz z typem lub metodą, w której jest zadeklarowana. Jest to jeden z powodów, dla których struktury są kopiowane podczas przypisywania. Natomiast pamięć przydzielona dla wystąpienia klasy jest automatycznie odzyskiwane (wyrzucanie pamięci) przez środowisko uruchomieniowe języka wspólnego, gdy wszystkie odwołania do obiektu wyszły poza zakres. Nie można deterministycznie zniszczyć obiektu klasy, takiego jak w języku C++. Aby uzyskać więcej informacji na temat odzyskiwania pamięci na platformie .NET, zobacz Odzyskiwanie pamięci.

Uwaga

Alokacja i cofanie alokacji pamięci na zarządzanym stercie jest wysoce zoptymalizowane w środowisku uruchomieniowym języka wspólnego. W większości przypadków nie ma znaczącej różnicy w kosztach wydajności przydzielania wystąpienia klasy na stercie, a nie przydzielania wystąpienia struktury na stosie.

Tożsamość obiektu a równość wartości

Podczas porównywania dwóch obiektów pod kątem równości należy najpierw odróżnić, czy dwie zmienne reprezentują ten sam obiekt w pamięci, czy też wartości jednego lub kilku pól są równoważne. Jeśli zamierzasz porównać wartości, należy rozważyć, czy obiekty są wystąpieniami typów wartości (struktur) lub typów referencyjnych (klas, delegatów, tablic).

  • Aby określić, czy dwa wystąpienia klasy odwołują się do tej samej lokalizacji w pamięci (co oznacza, że mają tę samą tożsamość), użyj metody statycznej Object.Equals . (System.Object jest niejawną klasą bazową dla wszystkich typów wartości i typów referencyjnych, w tym struktur zdefiniowanych przez użytkownika i klas).

  • Aby określić, czy pola wystąpienia w dwóch wystąpieniach struktury mają te same wartości, użyj ValueType.Equals metody . Ponieważ wszystkie struktury niejawnie dziedziczą z System.ValueTypeklasy , metoda jest wywoływana bezpośrednio w obiekcie, jak pokazano w poniższym przykładzie:

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

    Implementacja System.ValueType użycia boksu Equals i odbicia w niektórych przypadkach. Aby uzyskać informacje na temat zapewniania efektywnego algorytmu równości specyficznego dla danego typu, zobacz How to define value equality for a type (Jak zdefiniować równość wartości dla typu). Rekordy to typy referencyjne, które używają semantyki wartości w celu zapewnienia równości.

  • Aby określić, czy wartości pól w dwóch wystąpieniach klasy są równe, możesz użyć Equals metody lub operatora ==. Jednak należy ich używać tylko wtedy, gdy klasa przesłoniła lub przeciążyła je, aby zapewnić niestandardową definicję tego, co oznacza "równość" dla obiektów tego typu. Klasa może również implementować IEquatable<T> interfejs lub IEqualityComparer<T> interfejs. Oba interfejsy udostępniają metody, które mogą służyć do testowania równości wartości. Podczas projektowania własnych klas, które zastępują , upewnij się, że postępuj zgodnie z wytycznymi podanymi w temacie EqualsJak zdefiniować równość wartości dla typu i Object.Equals(Object).

Więcej informacji można znaleźć na stronie