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.
Feljegyzé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.
Strukturált pé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 az new
operátorral hozhatók létre. Az alábbi példában Person
a típus person1
person2
és az adott típusú példányok vagy objektumok szerepelnek.
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
*/
Mivel a szerkezetek értéktípusok, egy struct objektum változója a teljes objektum másolatát tartalmazza. A struktúrapéldányok az operátorral new
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 = {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
*/
}
A memória mindkettőhöz p1
, és p2
a szálveremen van lefoglalva. 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 rendszer átmásolja a szerkezeteket a hozzárendelésre. 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és című témakörben talál.
Feljegyzé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 teljesítményköltségében, szemben a verem egy strukturált példányának kiosztásával.
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 ugyanazzal az identitással rendelkeznek), használja a statikus Object.Equals metódust. (System.Object az implicit alaposztály az összes értéktípushoz és referenciatípushoz, 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 metódust ValueType.Equals . Mivel az összes struktúra implicit módon öröklődik System.ValueType, a metódust közvetlenül az objektumon kell meghívnia az alábbi példában látható módon:
// 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.
Bizonyos System.ValueType esetekben a ökölvívás és a tükröződés alkalmazása
Equals
. Az Ön típusára jellemző hatékony egyenlőségi algoritmus biztosításáról a Típus értékegyenlőségének meghatározása című témakörben olvashat. 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 az == 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 implementálhatja az interfészt IEquatable<T> vagy az interfészt IEqualityComparer<T> is. Mindkét interfész olyan módszereket biztosít, amelyekkel tesztelhető az értékegyenlőség. A felülbíráló
Equals
saját osztályok tervezésekor mindenképpen kövesse az értékegyenlőség meghatározásához a típus és Object.Equals(Object)a .
Kapcsolódó témakörök
További információk: