Partager via


Objets : créer des instances de types

Une définition de classe ou de struct est semblable à un blueprint qui spécifie ce que le type peut faire. Un objet est essentiellement un bloc de mémoire qui a été alloué et configuré en fonction du blueprint. Un programme peut créer de nombreux objets de la même classe. Les objets sont également appelés instances et peuvent être stockés dans une variable nommée ou dans un tableau ou une collection. Le code client est le code qui utilise ces variables pour appeler les méthodes et accéder aux propriétés publiques de l’objet. Dans un langage orienté objet tel que C#, un programme classique se compose de plusieurs objets qui interagissent dynamiquement.

Remarque

Les types statiques se comportent différemment de ce qui est décrit ici. Pour plus d’informations, consultez la page Classes statiques et membres de classes statiques.

Instances de structure et instances de classe

Étant donné que les classes sont des types de référence, une variable d’un objet de classe contient une référence à l’adresse de l’objet sur le tas managé. Si une deuxième variable du même type est affectée à la première variable, les deux variables font référence à l’objet à cette adresse. Ce point est abordé plus en détail plus loin dans cet article.

Les instances de classes sont créées à l’aide de l’opérateur new. Dans l’exemple suivant, Person est le type et person1 et person2 sont des instances ou des objets de ce 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 = {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
*/

Étant donné que les structs sont des types valeur, une variable d’un objet struct contient une copie de l’objet entier. Les instances de structs peuvent également être créées à l’aide de l’opérateur new, mais cela n’est pas obligatoire, comme indiqué dans l’exemple suivant :

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

La mémoire pour p1 et p2 est allouée sur la pile de threads. Cette mémoire est récupérée avec le type ou la méthode où elle est déclarée. C’est l’une des raisons pour lesquelles les structs sont copiés au moment de l’assignation. En revanche, la mémoire allouée pour une instance de classe est récupérée automatiquement (garbage collection) par le common language runtime quand toutes les références à l’objet sont hors de la portée. Il n’est pas possible de détruire de façon déterministe un objet de classe comme vous pouvez en C++. Pour plus d’informations sur l’opération de garbage collection dans .NET, consultez Garbage Collection.

Remarque

L’allocation et la libération de mémoire sur le tas managé sont des opérations très optimisées dans le common language runtime. Dans la plupart des cas, il n’y a pas de différence significative sur le plan des performances entre l’allocation d’une instance de classe sur le tas et l’allocation d’une instance de struct sur la pile.

Identité d’objet et égalité des valeurs

Lorsque vous comparez deux objets pour l’égalité, vous devez d’abord distinguer si vous souhaitez savoir si les deux variables représentent le même objet en mémoire, ou si les valeurs d’un ou plusieurs de leurs champs sont équivalentes. Si vous envisagez de comparer des valeurs, vous devez déterminer si les objets sont des instances de types valeur (structs) ou des types référence (classes, délégués, tableaux).

  • Pour déterminer si deux instances de classe font référence au même emplacement en mémoire (ce qui signifie qu’elles ont la même identité ), utilisez la méthode statique Object.Equals. (System.Object est la classe de base implicite pour tous les types valeur et types de référence, y compris les structs et classes définis par l’utilisateur.)

  • Pour déterminer si les champs d’instance dans deux instances de struct ont les mêmes valeurs, utilisez la méthode ValueType.Equals. Étant donné que tous les structs héritent implicitement de System.ValueType, vous appelez la méthode directement sur votre objet, comme indiqué dans l’exemple suivant :

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

    L’implémentation System.ValueType de Equals utilise le boxing et la réflexion dans certains cas. Pour plus d’informations sur la façon de fournir un algorithme d’égalité efficace spécifique à votre type, consultez Comment définir l’égalité des valeurs pour un type. Les enregistrements sont des types de référence qui utilisent la sémantique de valeur pour l’égalité.

  • Pour déterminer si les valeurs des champs dans deux instances de classe sont égales, vous pouvez utiliser la méthode Equals ou l’opérateur ==. Toutefois, utilisez-les uniquement si la classe les a substitués ou surchargés pour fournir une définition personnalisée de ce que signifie « égalité » pour les objets de ce type. La classe peut également implémenter l’interface IEquatable<T> ou l’interface IEqualityComparer<T>. Les deux interfaces fournissent des méthodes qui peuvent être utilisées pour tester l’égalité des valeurs. Lors de la conception de vos propres classes qui remplacent Equals, veillez à suivre les instructions indiquées dans Comment définir l’égalité des valeurs pour un type et Object.Equals(Object).

Pour plus d’informations :