Share via


Objecten - exemplaren van typen maken

Een klasse- of structdefinitie lijkt op een blauwdruk die aangeeft wat het type kan doen. Een object is in feite een blok geheugen dat is toegewezen en geconfigureerd volgens de blauwdruk. Een programma kan veel objecten van dezelfde klasse maken. Objecten worden ook wel exemplaren genoemd en kunnen worden opgeslagen in een benoemde variabele of in een matrix of verzameling. Clientcode is de code die deze variabelen gebruikt om de methoden aan te roepen en toegang te krijgen tot de openbare eigenschappen van het object. In een objectgeoriënteerde taal zoals C# bestaat een typisch programma uit meerdere objecten die dynamisch communiceren.

Notitie

Statische typen gedragen zich anders dan wat hier wordt beschreven. Zie Statische klassen en statische klasseleden voor meer informatie.

Struct Instances versus Class Instances

Omdat klassen verwijzingstypen zijn, bevat een variabele van een klasseobject een verwijzing naar het adres van het object op de beheerde heap. Als een tweede variabele van hetzelfde type is toegewezen aan de eerste variabele, verwijzen beide variabelen naar het object op dat adres. Dit punt wordt verderop in dit artikel nader besproken.

Exemplaren van klassen worden gemaakt met behulp van de new operator. In het volgende voorbeeld Person is dit het type en person1person2 het zijn exemplaren of objecten van dat type.

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

Omdat structs waardetypen zijn, bevat een variabele van een struct-object een kopie van het hele object. Exemplaren van structs kunnen ook worden gemaakt met behulp van de new operator, maar dit is niet vereist, zoals wordt weergegeven in het volgende voorbeeld:

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

Het geheugen voor beide p1 en p2 wordt toegewezen aan de threadstack. Dat geheugen wordt vrijgemaakt samen met het type of de methode waarin het wordt gedeclareerd. Dit is een van de redenen waarom structs worden gekopieerd bij de toewijzing. Het geheugen dat voor een klasse-exemplaar wordt toegewezen, wordt daarentegen automatisch vrijgemaakt (garbage verzameld) door de algemene taalruntime wanneer alle verwijzingen naar het object buiten het bereik zijn gegaan. Het is niet mogelijk om een klasseobject deterministisch te vernietigen, zoals in C++. Zie Garbagecollection voor meer informatie over garbagecollection in .NET.

Notitie

De toewijzing en deallocatie van geheugen op de beheerde heap is sterk geoptimaliseerd in de algemene taalruntime. In de meeste gevallen is er geen significant verschil in de prestatiekosten van het toewijzen van een klasse-exemplaar aan de heap versus het toewijzen van een struct-exemplaar op de stack.

Objectidentiteit versus waarde gelijkheid

Wanneer u twee objecten vergelijkt voor gelijkheid, moet u eerst onderscheid maken of u wilt weten of de twee variabelen hetzelfde object in het geheugen vertegenwoordigen of of de waarden van een of meer velden gelijkwaardig zijn. Als u waarden wilt vergelijken, moet u overwegen of de objecten exemplaren zijn van waardetypen (structs) of verwijzingstypen (klassen, gemachtigden, matrices).

  • Gebruik de statische Object.Equals methode om te bepalen of twee klasse-exemplaren verwijzen naar dezelfde locatie in het geheugen (wat betekent dat ze dezelfde identiteit hebben). (System.Object is de impliciete basisklasse voor alle waardetypen en referentietypen, inclusief door de gebruiker gedefinieerde structs en klassen.)

  • Gebruik de ValueType.Equals methode om te bepalen of de instantievelden in twee struct-exemplaren dezelfde waarden hebben. Omdat alle structs impliciet overnemen van System.ValueType, roept u de methode rechtstreeks aan op uw object, zoals wordt weergegeven in het volgende voorbeeld:

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

    De System.ValueType implementatie van Equals boksen en reflectie in sommige gevallen. Zie How to define value equality for a type (Waarde gelijkheid definiëren voor een type) voor informatie over het bieden van een efficiënt gelijkheidsalgoritmen die specifiek zijn voor uw type. Records zijn referentietypen die gebruikmaken van waardesemantiek voor gelijkheid.

  • Als u wilt bepalen of de waarden van de velden in twee klasse-exemplaren gelijk zijn, kunt u mogelijk de Equals methode of de operator == gebruiken. Gebruik ze echter alleen als de klasse deze heeft overschreven of overbelast om een aangepaste definitie te geven van wat "gelijkheid" betekent voor objecten van dat type. De klasse kan ook de IEquatable<T> interface of de IEqualityComparer<T> interface implementeren. Beide interfaces bieden methoden die kunnen worden gebruikt om gelijkheid van waarden te testen. Bij het ontwerpen van uw eigen klassen die worden overschreven Equals, moet u de richtlijnen volgen die worden vermeld in How to define value equality for a type and Object.Equals(Object).

Bekijk voor meer informatie: