2010-11-18 33 views
5

quelle déclaration/instanciation est la meilleure et POURQUOI?Créer un objet dans le constructeur ou en haut de la classe

public class MainWindow 
{ 
    private Test _test; 

    public MainWindow() 
    { 
     _test = new Test(); 
    } 
} 

OU

public class MainWindow 
{ 
    private Test _test = new Test(); 

    public MainWindow() 
    { 

    } 
} 
+1

Duplication d'un doublon d'un .... Voir http://stackoverflow.com/questions/298183/c-member-variable-initialization-best-practice – Tony

Répondre

2

Posez-vous cette question: que se passe-t-il lorsque vous ajoutez d'autres constructeurs à MainWindow? Voulez-vous alors vous souvenir de vous référer à d'autres constructeurs pour vous assurer que _test est correctement initialisé? Ou est-il correct que _test ne soit pas initialisé si un autre constructeur est utilisé?

Personnellement lors de la création d'un composant d'interface utilisateur, je propose autant de points de défaillance sur le constructeur que possible, et je proposerais quelque chose comme ça soit le gestionnaire d'événements Loaded, ou le garder comme vous l'avez fait dans l'option 2.

0

Ce dernier, parce que la déclaration et l'initialisation se produisent sur la même ligne ... plus facile à lire, plus difficile de faire une erreur.

2

Je vais pour une troisième option:

public class MainWindow 
{ 
    private Test _test; 

    public MainWindow(Test test) 
    { 
     _test = test; 
    } 
} 

En injectant la dépendance vous rendre votre code plus facile à tester l'unité.

+0

L'OP avait '_test' comme variable membre de la classe, ce qui signifie qu'elle ne doit pas être testable séparément de 'MainWindow', à la place, le test devrait viser' MainWindow'. IOW: IoC est inapproprié pour '_test'. – slugster

+0

De cette façon, vous pouvez vous moquer lors des tests. –

+0

@slugster: Cela dépend de ce que fait Test. Il DEVRAIT être injecté s'il fournit n'importe quel type de données à MainWindow. Vous obtenez un résultat prédéfini (testable) si vous pouvez fournir ces données à partir de votre test (à travers un objet tronqué/mocké) – jgauffin

1

C'est la même que la différence entre

int i; 
... 
i = 0; 

et

int i = 0; 

Mon opinion est que l'initialisation devrait être proche de la déclaration, si possible, en cas idéal une partie de celui-ci. Outre le bonus de lisibilité, vous avez moins de chances d'oublier l'initialisation. Donc la 2ème variante est meilleure.

2

Il est préférable de le faire à l'intérieur du constructeur pour rendre clair ce qui se passe lorsque l'objet est créé, en particulier lorsque vous allez écrire des sous-classes.

Généralement bien que ce soit une question de goût et le plus important est d'être conforme dans votre choix.

1

Je ne pense pas que vous puissiez dire qu'une déclaration est meilleure que l'autre, tout dépend de la logique de votre formulaire, si vous ne voulez pas lancer le test au démarrage du formulaire, mais sur un bouton cliquez ensuite la première déclaration est meilleure.

+0

+1: L'instanciation paresseuse peut être très utile. – Tony

+0

C'est vrai, si "new Test()" implique une utilisation intensive de la mémoire, il est plus sage d'appeler seulement si nécessaire, comme un événement de bouton ou quand il est impératif de créer une classe de test de type. –

0

Le second est le plus propre. En général, je ne crée des objets dans le constructeur que lorsqu'ils doivent être initialisés avec des paramètres.

Aucun paramètre

public class MainWindow 
{ 
    private Test _test = new Test(); 

    public MainWindow() 
    { 

    } 
} 

avec des paramètres:

public class MainWindow 
{ 
    private Test _test; 

    public MainWindow() 
    { 
     _test = new Test("abc") 
    } 
} 

Comme Jackson le pape dit, il peut être une bonne idée d'ajouter un constructeur de l'objet pour le rendre plus facile de commencer à utiliser DI est plus tard. Vous pouvez lire à propos de DI/IoC ici: http://www.codeproject.com/KB/architecture/DependencyInjection.aspx

0

Dans l'exemple que vous avez donné, aucun des choix n'est meilleur. Ces deux snippets instancient une variable membre pendant la construction de la classe. La seule vraie différence est que, dans le second cas, le membre est initialisé avant que le constructeur soit exécuté.

La seule fois que cela fait vraiment une différence est lorsque la variable membre a besoin d'informations passé dans son constructeur que la classe principale obtient dans son constructeur. Ensuite, vous n'avez pas d'autre choix que d'utiliser la deuxième option.

Par exemple:

public class MainWindow 
{ 
    private Test _test; 

    public MainWindow(int i) 
    { 
     _test = new Test(i); 
    } 
} 
0

Il ne fait pas de différence du tout, parce que le compilateur génère exactement la même IL. En termes de lisibilité, c'est juste une question de goût personnel. Je préfère cette dernière version, mais avec le modificateur readonly:

public class MainWindow 
{ 
    private readonly Test _test = new Test(); 

    public MainWindow() 
    { 

    } 
} 

Ceci est particulièrement facile à lire et à maintenir lorsque la classe a plus d'un constructeur.

+0

Dans l'exemple donné, c'est vrai, mais quand 'MainWindow' serait dérivé d'une autre classe, il y a une différence: dans le second cas' Test' sera construit _avant le constructeur de base. – Vlad