C# de membre de l'initialisation d'une variable; les meilleures pratiques?
Est-il préférable d'initialiser les variables de membre de classe sur la déclaration
private List<Thing> _things = new List<Thing>();
private int _arb = 99;
ou dans le constructeur par défaut?
private List<Thing> _things;
private int _arb;
public TheClass()
{
_things = new List<Thing>();
_arb = 99;
}
Est-ce simplement une question de style ou il y a la performance de compromis, d'une façon ou de l'autre?
- Double Possible de stackoverflow.com/questions/24551/...
Vous devez vous connecter pour publier un commentaire.
En termes de performance, il n'y a pas de différence réelle; champ initialiseurs sont mis en œuvre en tant que constructeur de la logique. La seule différence est que le champ des initialiseurs d'arriver avant tout "de base"/"ce" constructeur.
Le constructeur approche peut être utilisée avec des propriétés implémentées automatiquement (champ initialiseurs ne peut pas) - c'est à dire
Autre que cela, j'ai tendance à préférer le domaine de l'initialiseur de la syntaxe; je trouve qu'il garde les choses localisée à - dire
Je n'ai pas à aller à la chasse en haut et en bas pour trouver où il est affecté...
L'exception évidente est l'endroit où vous avez besoin pour effectuer une logique complexe ou de traiter avec les paramètres du constructeur, auquel cas le constructeur-en fonction d'initialisation est le chemin à parcourir. De même, si vous disposez de plusieurs constructeurs, il serait préférable pour les champs pour avoir toujours définie de la même manière que vous pourriez avoir ctors comme:
edit: comme un commentaire, remarque que ci-dessus, si il y a d'autres champs (non illustré) avec le champ des initialiseurs, alors qu'ils ne sont directement initialisé dans le constructeur que l'appel
base(...)
- à-dire lepublic Bar(string foo)
ctor. L'autre constructeur ne pas champ exécuter les initialiseurs, car il sait qu'ils sont fait par lethis(...)
ctor.class
, chaque constructeur implicite: base()
, sauf si vous ajoutez quelque chose de plus précis, ce qui pourrait être: base(123, "abc")
, ou pourrait être: this(123, "abc")
.En fait, le champ des initialiseurs comme vous le démontrer est un raccourci pratique. Le compilateur fait des copies le code d'initialisation au début de chaque instance constructeur que vous définissez pour votre type.
Cela a deux conséquences: d'abord, un champ de code d'initialisation est dupliqué dans chaque constructeur et, d'autre part, tout le code que vous incluez dans votre constructeur pour initialiser les champs de valeurs spécifiques sera en effet re-assigner les champs.
Donc en terme de performance, et en ce qui concerne le code compilé de la taille, vous êtes mieux de déplacer le champ des initialiseurs dans les constructeurs.
D'autre part, l'impact sur les performances et le code 'gonfler' sera généralement négligeable, et que le champ d'initialiseur de syntaxe a l'avantage de diminuer le risque que vous pourriez oublier d'initialiser le terrain, dans l'un de vos constructeurs.
L'une des principales limites du terrain initialiseurs est qu'il n'y a aucun moyen de les envelopper dans un try-finally bloc. Si une exception est levée dans un champ d'initialiseur, toutes les ressources qui ont été allouées dans les précédents initialiseurs sera abandonné; il n'y a aucun moyen de l'empêcher. D'autres erreurs dans la construction peuvent être traitées, si maladroitement, par le fait d'avoir protégé constructeur de base accepter une IDisposable par référence, et pointant à sa première opération. On peut alors éviter d'appeler le constructeur, sauf par l'intermédiaire de méthodes de fabrique qui, dans des cas d'exception appeler dispose sur la partie objet créé. Cette protection permettra de nettoyage de IDisposables créé en dérivés de la classe des initialiseurs si le principal constructeur de la classe échoue après la "contrebande" une référence à l'objet nouveau. Malheureusement, il n'y a aucun moyen de fournir cette protection si un champ d'initialiseur échoue.
Utiliser soit le champ d'initialiseurs ou de créer une fonction Init (). Le problème avec mettre ces choses dans votre constructeur, c'est que si jamais vous avez besoin d'ajouter un 2ème constructeur, vous vous retrouvez avec des copier/coller le code (ou vous l'ignorer, et à la fin avec des variables non initialisées).
Je voudrais soit initialiser où déclarée. Ou ont le constructeur(s) de l'appel d'une fonction Init ().
Pour les variables d'instance, c'est en grande partie une question de style (je préfère à l'aide d'un constructeur). Pour les variables statiques, il y a un avantage en matière de performances à l'initialisation en ligne (pas toujours possible, bien sûr).
C'est vraiment à vous.
J'ai souvent les initialiser en ligne, parce que je n'aime pas avoir un constructeur quand je n'en ai pas vraiment besoin (j'aime les petits des classes !).
Sur ajouté des points au - dessus de Vous de toujours avoir un constructeur lors de la mise en œuvre de classes qui ont une mise en œuvre. Si vous ne déclarez pas un, alors la valeur par défaut de l'instructeur est déduit par le compilateur [public Foo(){}]; un constructeur qui ne prend pas d'arguments.
Bien souvent, je tiens à offrir les deux approches. Permettre à des constructeurs pour ceux qui souhaitent les utiliser et d'autoriser le Domaine des Initialiseurs pour les situations où vous souhaitez utiliser une procédure simplifiée ou par défaut de mise en œuvre de votre classe /type. Cela ajoute de la souplesse à votre code. Gardez à l'esprit que n'importe qui peut utiliser la valeur par défaut du champ de l'initialiseur s'ils choisissent ... assurez-vous de déclarer manuellement si vous offrez plus d'un constructeur - public: Foo(){}