Megosztás a következőn keresztül:


Objektumok – típusok példányainak létrehozása

Az osztály- vagy szerkezetdefiníció olyan, mint egy terv, amely meghatározza, hogy mit tehet a típus. Az objektum alapvetően egy memóriablokk, amely a terv szerint lett lefoglalva és konfigurálva. Egy program több objektumot is létrehozhat ugyanahhoz az osztályhoz. Az objektumokat példányoknak is nevezik, és elnevezett változókban, tömbökben vagy gyűjteményekben tárolhatók. Az ügyfélkód az a kód, amely ezeket a változókat használja a metódusok meghívására és az objektum nyilvános tulajdonságainak elérésére. Egy objektumorientált nyelvben, például a C#-ban egy tipikus program több, dinamikusan kommunikáló objektumból áll.

Megjegyzés

A statikus típusok másképp viselkednek, mint az itt leírtak. További információ: Statikus osztályok és statikus osztálytagok.

Struktúrapéldányok és osztálypéldányok

Mivel az osztályok referenciatípusok, az osztályobjektumok változói a felügyelt halom objektumának címére mutató hivatkozást tárolnak. Ha az első változóhoz egy azonos típusú második változó van hozzárendelve, akkor mindkét változó az adott címen található objektumra hivatkozik. Ezt a pontot a cikk későbbi részében részletesebben tárgyaljuk.

Az osztályok példányai a new operátorhasználatával jönnek létre. Az alábbi példában Person a típus, a person1 és a person2 pedig az adott típusú példányok vagy objektumok.

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 = {person1.Name} Age = {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 = {person2.Name} Age = {person2.Age}");
        Console.WriteLine($"person1 Name = {person1.Name} Age = {person1.Age}");
    }
}
/*
    Output:
    person1 Name = Leopold Age = 6
    person2 Name = Molly Age = 16
    person1 Name = Molly Age = 16
*/

Mivel a szerkezetek értéktípusok, egy struct objektum változója a teljes objektum másolatát tartalmazza. A szerkezetpéldányok a new operátorral is létrehozhatók, de ez nem kötelező, ahogy az alábbi példában látható:

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 = {p1.Name} Age = {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 = {p2.Name} Age = {p2.Age}");

            // p1 values remain unchanged because p2 is  copy.
            Console.WriteLine($"p1 Name = {p1.Name} Age = {p1.Age}");
        }
    }
    /*
        Output:
        p1 Name = Alex Age = 9
        p2 Name = Spencer Age = 7
        p1 Name = Alex Age = 9
    */
}

A p1 és a p2 memóriája a szálveremen le van foglalva. A memória visszanyerése a deklarált típussal vagy módszerrel együtt történik. Ez az egyik oka annak, hogy a struktúrák másolódnak hozzárendeléskor. Ezzel szemben az osztálypéldányhoz lefoglalt memóriát a közös nyelvi futtatókörnyezet automatikusan visszanyeri (szemétgyűjtés), amikor az objektumra mutató összes hivatkozás kifogyott a hatókörből. Nem lehet determinisztikus módon megsemmisíteni egy osztályobjektumot, mint a C++-ban. A .NET-beli szemétgyűjtésről további információt a Szemétgyűjtéscímű témakörben talál.

Megjegyzés

A memória lefoglalása és felszabadítása a felügyelt halomon nagy mértékben optimalizálva van a közös nyelvi futtatókörnyezetben. A legtöbb esetben nincs jelentős különbség az osztálypéldányok halomra történő kiosztásának és a struktúrapéldányok verembe történő kiosztásának teljesítményköltségében.

Objektumdentitás és értékegyenlőség

Ha összehasonlít két objektumot az egyenlőség érdekében, először meg kell különböztetnie, hogy tudni szeretné, hogy a két változó ugyanazt az objektumot jelöli-e a memóriában, vagy egy vagy több mező értéke egyenértékű-e. Ha értékeket szeretne összehasonlítani, mérlegelnie kell, hogy az objektumok értéktípusok (szerkezetek) vagy referenciatípusok (osztályok, meghatalmazottak, tömbök) példányai-e.

  • Annak megállapításához, hogy két osztálypéldány ugyanarra a helyre hivatkozik-e a memóriában (ami azt jelenti, hogy azonos identitással), használja a statikus Object.Equals metódust. (System.Object az összes értéktípus és referenciatípus implicit alaposztálya, beleértve a felhasználó által definiált szerkezeteket és osztályokat.)

  • Annak megállapításához, hogy a két strukturált példány példánymezői azonos értékekkel rendelkeznek-e, használja a ValueType.Equals metódust. Mivel minden struktúra implicit módon a System.ValueType-től örököl, a metódust közvetlenül az objektumán hívhatja meg, ahogy az alábbi példában látható.

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

    A System.ValueType megvalósítása a Equals-ben bizonyos esetekben dobozolást és reflexiót használ. A típusra jellemző hatékony egyenlőségi algoritmus biztosításáról további információt Az értékegyenlőség meghatározásacímű témakörben talál. A rekordok olyan referenciatípusok, amelyek értékszemantikát használnak az egyenlőséghez.

  • Annak megállapításához, hogy a két osztálypéldány mezői egyenlők-e, használhatja a Equals metódust vagy a == operátort. Azonban csak akkor használja őket, ha az osztály felülbírálta vagy túlterhelte őket, hogy egyéni definíciót adjon arról, hogy mit jelent az "egyenlőség" az ilyen típusú objektumok esetében. Az osztály a IEquatable<T> felületet vagy a IEqualityComparer<T> felületet is implementálhatja. Mindkét interfész olyan módszereket biztosít, amelyekkel tesztelhető az értékegyenlőség. Amikor saját osztályokat tervez, amelyek felülbírálják a Equals-t, feltétlenül kövesse az irányelveket, amelyeket az Értékegyenlőség meghatározása egy típushoz és Object.Equals(Object)című dokumentumban ismertetnek.

További információ: