Sdílet prostřednictvím


Objekty – vytváření instancí typů

Definice třídy nebo struktury je jako podrobný plán, který určuje, co může typ dělat. Objekt je v podstatě blok paměti, který byl přidělen a nakonfigurován podle podrobného plánu. Program může vytvořit mnoho objektů stejné třídy. Objekty se také nazývají instance a mohou být uloženy buď v pojmenované proměnné, nebo v poli nebo kolekci. Kód klienta je kód, který tyto proměnné používá k volání metod a přístup k veřejným vlastnostem objektu. V objektově orientovaném jazyce, jako je C#, se typický program skládá z více objektů, které interagují dynamicky.

Poznámka:

Statické typy se chovají jinak než zde popsané. Další informace naleznete v tématu Statické třídy a členy statické třídy.

Instance struktury vs. instance tříd

Vzhledem k tomu, že třídy jsou odkazové typy, proměnná objektu třídy obsahuje odkaz na adresu objektu ve spravované haldě. Pokud je k první proměnné přiřazena druhá proměnná stejného typu, obě proměnné odkazují na objekt na této adrese. Tento bod je podrobněji popsán dále v tomto článku.

Instance tříd se vytvářejí pomocí operátorunew. V následujícím příkladu Person je typ a person1person2 jsou instancemi nebo objekty tohoto 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
*/

Vzhledem k tomu, že struktury jsou typy hodnot, proměnná objektu struktury obsahuje kopii celého objektu. Instance struktur lze také vytvořit pomocí operátoru new , ale to není povinné, jak je znázorněno v následujícím příkladu:

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

Paměť pro obě p1 a p2 je přidělena v zásobníku vláken. Tato paměť je uvolněna spolu s typem nebo metodou, ve které je deklarována. To je jeden z důvodů, proč se struktury kopírují při přiřazení. Naproti tomu paměť přidělená pro instanci třídy je automaticky uvolněna (uvolňování paměti) modulem CLR (Common Language Runtime), když všechny odkazy na objekt zmizely z oboru. Není možné deterministicky zničit objekt třídy, jako je v jazyce C++. Další informace o uvolňování paměti v .NET naleznete v tématu Uvolňování paměti.

Poznámka:

Přidělení a uvolnění paměti ve spravované haldě je vysoce optimalizované v modulu CLR (Common Language Runtime). Ve většině případů není žádný významný rozdíl v nákladech na výkon přidělení instance třídy na haldě a přidělení instance struktury v zásobníku.

Identita objektu versus rovnost hodnot

Při porovnávání dvou objektů pro rovnost je třeba nejprve rozlišit, zda chcete zjistit, zda tyto dvě proměnné představují stejný objekt v paměti, nebo zda jsou hodnoty jednoho nebo více polí ekvivalentní. Pokud máte v úmyslu porovnávat hodnoty, musíte zvážit, jestli jsou objekty instancemi typů hodnot (struktury) nebo odkazovými typy (třídy, delegáty, matice).

  • Chcete-li zjistit, zda dvě instance třídy odkazují na stejné umístění v paměti (což znamená, že mají stejnou identitu), použijte statickou Object.Equals metodu. (System.Object je implicitní základní třída pro všechny typy hodnot a odkazové typy, včetně uživatelem definovaných struktur a tříd.)

  • Chcete-li zjistit, zda pole instance ve dvou instancích struktury mají stejné hodnoty, použijte metodu ValueType.Equals . Vzhledem k tomu, že všechny struktury implicitně dědí z System.ValueType, voláte metodu přímo na objektu, jak je znázorněno v následujícím příkladu:

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

    Implementace System.ValueTypeEquals použití boxingu a reflexe v některých případech. Informace o tom, jak poskytnout efektivní algoritmus rovnosti, který je specifický pro váš typ, najdete v tématu Definování rovnosti hodnot pro typ. Záznamy jsou odkazové typy, které pro rovnost používají sémantiku hodnot.

  • Chcete-li zjistit, zda jsou hodnoty polí ve dvou instancích třídy stejné, můžete být schopni použít metodu Equalsnebo operátor == . Použijte je však pouze v případě, že třída přepsala nebo přetížila, aby poskytla vlastní definici toho, co "rovnost" znamená pro objekty tohoto typu. Třída může také implementovat IEquatable<T> rozhraní nebo IEqualityComparer<T> rozhraní. Obě rozhraní poskytují metody, které lze použít k otestování rovnosti hodnot. Při navrhování vlastních tříd, které přepisují Equals, nezapomeňte postupovat podle pokynů uvedených v tématu Jak definovat rovnost hodnot pro typ a Object.Equals(Object).

Další informace: