197 votes

Quelle est la différence entre un initialisateur d'objet et un constructeur ?

Quelles sont les différences entre les deux et quand utiliseriez-vous un "initialisateur d'objet" plutôt qu'un "constructeur" et vice-versa ? Je travaille avec C#, si cela a de l'importance. Par ailleurs, la méthode de l'initialisateur d'objet est-elle spécifique à C# ou à .NET ?

260voto

Reed Copsey Points 315315

Les initialisateurs d'objets ont été ajoutés au C# 3, afin de simplifier la construction d'objets lorsque vous utilisez un objet.

Les constructeurs s'exécutent, avec 0 ou plusieurs paramètres, et sont utilisés pour créer et initialiser un objet. avant la méthode appelante obtient l'identifiant de l'objet créé. Par exemple :

MyObject myObjectInstance = new MyObject(param1, param2);

Dans ce cas, le constructeur de MyObject sera exécuté avec les valeurs param1 y param2 . Ces deux éléments sont utilisés pour créer le nouveau MyObject en mémoire. L'objet créé (qui est configuré à l'aide de ces paramètres) est retourné, et mis à la valeur myObjectInstance .

En général, il est considéré comme une bonne pratique qu'un constructeur exige les paramètres nécessaires à la configuration complète d'un objet, afin qu'il soit impossible de créer un objet dans un état invalide.

Cependant, il existe souvent des propriétés "supplémentaires" qui peuvent être définies, mais qui ne sont pas obligatoires. Cela pourrait être géré par des constructeurs surchargés, mais cela conduit à avoir beaucoup de constructeurs qui ne sont pas nécessairement utiles dans la majorité des circonstances.

Cela conduit aux initialisateurs d'objets - Un initialisateur d'objet vous permet de définir des propriétés ou des champs sur votre objet. après il a été construit, mais avant vous pouvez l'utiliser pour n'importe quoi d'autre. Par exemple :

MyObject myObjectInstance = new MyObject(param1, param2)
{
    MyProperty = someUsefulValue
};

Le comportement sera à peu près le même que si vous faites ceci :

MyObject myObjectInstance = new MyObject(param1, param2);
myObjectInstance.MyProperty = someUsefulValue;

Cependant, en multithreading l'atomicité de l'initialisateur de l'objet peut être bénéfique, puisqu'elle empêche l'objet de se trouver dans un état non complètement initialisé (cf. cette réponse pour plus de détails) - il est soit nul, soit initialisé comme vous l'aviez prévu.

De plus, les initialisateurs d'objets sont plus simples à lire (en particulier lorsque vous définissez plusieurs valeurs), ils vous offrent donc le même avantage que de nombreuses surcharges sur le constructeur, sans qu'il soit nécessaire d'avoir de nombreuses surcharges compliquant l'API de cette classe.

50 votes

Je suis d'accord, mais je voudrais ajouter que le débogage de l'initialisateur d'objet peut être pénible, surtout si vous avez une structure imbriquée, puisque l'initialisateur d'objet est considéré comme une ligne de code (joliment formatée), tout comme ma phrase.

0 votes

@Reed-Copsey très bonne explication, y aura-t-il des gains de performance avec les initialisateurs d'objets ou est-ce seulement pour la lisibilité ?

2 votes

@Mahender En fait, l'utilisation d'initialisateurs d'objets entraîne généralement des pertes de performances (très, très faibles). Les constructeurs peuvent être écrits pour être plus efficaces.

53voto

JaredPar Points 333733

Un constructeur est une méthode définie sur un type qui prend un nombre spécifié de paramètres et qui est utilisée pour créer et initialiser un objet.

Un initialisateur d'objet est un code qui s'exécute sur un objet après un constructeur et peut être utilisé pour définir succinctement un certain nombre de champs de l'objet à des valeurs spécifiées. La définition de ces champs se fait après le constructeur est appelé.

Vous utiliserez un constructeur sans l'aide d'un initialisateur d'objet si le constructeur définit suffisamment l'état initial de l'objet. Un initialisateur d'objet doit cependant être utilisé en conjonction avec un constructeur. La syntaxe exige l'utilisation explicite ou implicite (VB.Net et C#) d'un constructeur pour créer l'objet initial. Vous utiliserez un initialisateur d'objet lorsque le constructeur n'initialise pas suffisamment l'objet pour votre usage et que quelques simples champs et/ou propriétés le feraient.

0 votes

Il pourrait être bon d'ajouter que c'est le constructeur par défaut qui est appelé lorsqu'un initialisateur d'objet est invoqué, juste pour la lucidité.

0 votes

Je viens de corriger un problème de null ref, parce que quelqu'un pensait que ce n'était pas après.

37voto

nawfal Points 13500

Quand vous le faites

Person p = new Person { Name = "a", Age = 23 };

c'est ce que fait essentiellement un initialisateur d'objet :

Person tmp = new Person(); //creates temp object calling default constructor
tmp.Name = "a";
tmp.Age = 23;
p = tmp;

Cela facilite un comportement comme este . Il est important de savoir comment fonctionnent les initialisateurs d'objets.

0 votes

Est-ce que ça peut être simplement Personne p = nouvelle Personne {Nom = "a"} ?

0 votes

@nick-s oui, beaucoup. C'est à cela que sert l'initialisateur d'objet. Vous initialisez les membres que vous voulez.

4 votes

Je ne savais pas que les paranthèses des constructeurs pouvaient être ignorées. Merci.

19voto

marc_s Points 321990

Si vous avez des propriétés qui DOIVENT être définies sur votre objet pour qu'il fonctionne correctement, une solution consiste à exposer un seul constructeur qui requiert ces propriétés obligatoires comme paramètres.

Dans ce cas, vous ne pouvez pas créer votre objet sans spécifier ces propriétés obligatoires. Une telle chose ne peut pas être imposée par les initialisateurs d'objets.

Les initialisateurs d'objets ne sont en fait qu'une "commodité syntaxique" permettant de raccourcir les affectations initiales. Sympathique, mais pas vraiment très pertinent d'un point de vue fonctionnel.

Marc

1 votes

Une autre façon de s'assurer que les propriétés essentielles sont définies sur un objet au moment de la construction est de fournir une méthode statique ("factory") sur une classe qui renvoie un objet construit. Cette méthode d'usine construit l'objet via un privé constructeur. (Définir plusieurs constructeurs privés peut être utile).

0 votes

...De même, il est parfois utile de créer une usine statique classe qui a la responsabilité de construire des instances d'une ou plusieurs autres classes. Par exemple, voir Méthode File.Create (String) (et ses surcharges), qui crée un fichier FileStream objet.

4voto

emaster70 Points 3201

Un constructeur est une méthode acceptant (éventuellement) des paramètres et retournant une nouvelle instance d'une classe. Il peut contenir une logique d'initialisation. Ci-dessous, vous pouvez voir un exemple de constructeur.

public class Foo
{
    private SomeClass s;
    public Foo(string s)
    {
       s = new SomeClass(s);
    }
}

Considérons maintenant l'exemple suivant :

public class Foo
{
    public SomeClass s { get; set; }
    public Foo() {}
}

Vous pourriez obtenir le même résultat que dans le premier exemple en utilisant un initialisateur d'objet, en supposant que vous pouvez accéder à SomeClass, avec le code suivant :

new Foo() { s = new SomeClass(someString) }

Comme vous pouvez le voir, un initialisateur d'objet vous permet de spécifier des valeurs pour les champs publics et les propriétés publiques (paramétrables) en même temps que la construction est effectuée, et c'est particulièrement utile lorsque le constructeur ne fournit pas de surcharge initialisant certains champs. N'oubliez pas, cependant, que les initialisateurs d'objets ne sont que du sucre syntaxique et qu'après la compilation, ils ne seront pas vraiment différents d'une séquence d'affectations.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X