Question

Supposons que j'ai une classe "Application". Pour être initialisé, il faut certains paramètres dans le constructeur. Supposons également que le nombre de paramètres est si important qu'il est impératif de les placer dans une classe à part.

Comparez les deux implémentations suivantes de ce scénario.

Mise en oeuvre 1:

class Application 
{
   Application(ApplicationSettings settings) 
   {
       //Do initialisation here
   }
}

class ApplicationSettings 
{
   //Settings related methods and properties here
}

Mise en œuvre 2:

class Application 
{
   Application(Application.Settings settings) 
   {
       //Do initialisation here
   }

   class Settings 
   {
      //Settings related methods and properties here
   }
}

Pour moi, la deuxième approche est de loin préférable. Il est plus lisible car il souligne fortement la relation entre les deux classes. Lorsque j'écris du code pour instancier une classe d'application n'importe où, la deuxième approche sera plus jolie.

Maintenant, imaginez que la classe Settings elle-même ait à son tour des expressions similaires "liées". la classe et cette classe l’ont fait à leur tour. Allez seulement trois de ces niveaux et le nommage de classe devient hors de contrôle dans le cas «non imbriqué». Si vous faites votre nid, les choses restent élégantes.

En dépit de ce qui précède, j'ai lu sur StackOverflow que des classes imbriquées ne sont justifiées que si elles ne sont pas visibles pour le monde extérieur. c'est-à-dire s'ils ne sont utilisés que pour l'implémentation interne de la classe contenue. L’objection fréquemment invoquée est de gonfler la taille du fichier source de la classe contenante, mais les classes partielles sont la solution parfaite à ce problème.

Ma question est la suivante: pourquoi nous méfions-nous des "exposés publiquement"? utilisation de classes imbriquées? Existe-t-il d'autres arguments contre une telle utilisation?

Était-ce utile?

La solution

Je pense que ça va. Il s’agit essentiellement du modèle de construction, et l’utilisation de classes imbriquées fonctionne plutôt bien. Il permet également au générateur d’accéder aux membres privés de la classe externe, ce qui peut être très utile. Par exemple, vous pouvez avoir une méthode Build sur le générateur qui appelle un constructeur privé sur la classe externe qui prend une instance du générateur:

public class Outer
{
    private Outer(Builder builder)
    {
        // Copy stuff
    }

    public class Builder
    {
        public Outer Build()
        {
            return new Outer(this);
        }
    }
}

Cela garantit que le seul moyen de créer une instance de la classe externe se fait via le générateur.

J'utilise un modèle très semblable à celui-ci dans mon port C # de tampons de protocole.

Autres conseils

Vous pouvez utiliser les espaces de noms pour relier des éléments ... liés.

Par exemple:

namespace Diner
{
    public class Sandwich
    {
        public Sandwich(Filling filling) { }
    }

    public class Filling { }
}

L’avantage de cela par rapport à l’utilisation de classes comme s’il s’agissait d’espaces de noms, c’est que vous pouvez éventuellement utiliser en utilisant du côté appelant pour abréger les choses:

using Diner;

...

var sandwich = new Sandwich(new Filling());

Si vous utilisez la classe Sandwich comme s'il s'agissait d'un espace de noms pour Remplissage , vous devez utiliser le nom complet Sandwich.Filling pour reportez-vous à Remplissage .

Et comment allez-vous dormir la nuit en sachant cela?

Vous voudrez peut-être vérifier ce que Microsoft doit dire sur le sujet. En gros, c’est une question de style, je dirais.

Un autre exemple pratique dont je dispose pour une utilisation valide des classes imbriquées publiques est le modèle MVC lorsque j'utilise un modèle de vue avec une propriété IEnumerable. par exemple:

public class OrderViewModel
{
public int OrderId{ get; set; }
public IEnumerable<Product> Products{ get; set; }

public class Product {
public string ProductName{ get; set; }
public decimal ProductPrice{ get; set; }
}

}

Je l'utilise parce que je ne souhaite pas que la classe Product soit réutilisée à l'extérieur, car elle n'est personnalisée que pour ce modèle de vue spécifique qui la contient. Mais je ne peux pas le rendre privé car la propriété Products est publique.

J'utilise principalement des classes imbriquées pour ajuster avec précision l'accès à la classe imbriquée et / ou à la classe conteneur.

Une chose à retenir est qu'une définition de classe imbriquée est fondamentalement un membre de la classe et aura accès à toutes les variables privées du conteneur.

Vous pouvez également l'utiliser pour contrôler l'utilisation d'une classe spécifique.

Exemple:

public abstract class Outer
{
  protected class Inner
  {
  }
}

Maintenant, dans ce cas, l'utilisateur (de votre classe) peut uniquement accéder à la classe Inner, s'il implémente Outer.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top