104 votes

Pourquoi/quand devriez-vous utiliser des classes imbriquées en .net? Ou ne devriez-vous pas?

Dans l'article de blog de Kathleen Dollard de 2008, elle présente une raison intéressante d'utiliser des classes imbriquées en .net. Cependant, elle mentionne également que FxCop n'aime pas les classes imbriquées. Je suppose que les personnes écrivant les règles de FxCop ne sont pas stupides, donc il doit y avoir une justification derrière cette position, mais je n'ai pas pu la trouver.

0 votes

Lien vers l'archive Wayback du billet de blog : web.archive.org/web/20141127115939/https://blogs.msmvps.com/‌​…

0 votes

Comme le souligne nawfal, notre ami Eric Lippert a répondu à une version en double de cette question ici, la réponse en question commençant par : "Utilisez des classes imbriquées lorsque vous avez besoin d'une classe d'aide qui n'a pas de signification en dehors de la classe ; en particulier lorsque la classe imbriquée peut utiliser des détails d'implémentation privés de la classe externe. Votre argument selon lequel les classes imbriquées sont inutiles est également un argument selon lequel les méthodes privées sont inutiles..."

109voto

hazzen Points 7315

Utilisez une classe imbriquée lorsque la classe que vous imbriquez n'est utile que pour la classe d'encapsulation. Par exemple, les classes imbriquées vous permettent d'écrire quelque chose comme (simplifié) :

public class SortedMap {
    private class TreeNode {
        TreeNode left;
        TreeNode right;
    }
}

Vous pouvez faire une définition complète de votre classe en un seul endroit, vous n'avez pas besoin de contourner des obstacles pour définir le fonctionnement de votre classe, et le monde extérieur n'a pas besoin de voir quoi que ce soit de votre implémentation.

Si la classe TreeNode était externe, vous auriez soit dû rendre tous les champs public, soit créer un tas de méthodes get/set pour l'utiliser. Le monde extérieur aurait eu une autre classe polluant leur intellisense.

45 votes

Pour compléter cela: Vous pouvez également utiliser des classes partielles dans des fichiers séparés pour mieux gérer votre code. Placez la classe interne dans un fichier séparé (SortedMap.TreeNode.cs dans ce cas). Cela devrait garder votre code propre, tout en le maintenant séparé :)

1 votes

Il y aura des cas où vous devrez rendre la classe imbriquée publique ou interne si elle est utilisée dans le type de retour d'une API publique ou d'une propriété publique de la classe conteneur. Je ne suis pas sûr que ce soit une bonne pratique cependant. Ces cas pourraient avoir plus de sens en extrayant la classe imbriquée de la classe conteneur. La classe System.Windows.Forms.ListViewItem.ListViewSubItem dans le framework .Net en est un exemple.

16voto

Esteban Araya Points 12496

Du tutoriel Java de Sun :

Pourquoi utiliser des classes imbriquées ? Il existe plusieurs raisons convaincantes d'utiliser des classes imbriquées, parmi lesquelles :

  • C'est une façon de regrouper logiquement des classes qui ne sont utilisées qu'à un seul endroit.
  • Cela augmente l'encapsulation.
  • Les classes imbriquées peuvent conduire à un code plus lisible et plus maintenable.

Regroupement logique de classes - Si une classe est utile à une seule autre classe, il est logique de l'inclure dans cette classe et de les garder ensemble. L'imbrication de telles "classes d'aide" rend leur package plus rationalisé.

Augmentation de l'encapsulation - Considérons deux classes de premier niveau, A et B, où B a besoin d'accéder à des membres de A qui seraient autrement déclarés privés. En cachant la classe B dans la classe A, les membres de A peuvent être déclarés privés et B peut y accéder. De plus, B lui-même peut être caché du monde extérieur. <- Cela ne s'applique pas à l'implémentation des classes imbriquées en C#, cela s'applique uniquement à Java.

Code plus lisible et plus maintenable - L'imbrication de petites classes au sein de classes de premier niveau place le code plus près de l'endroit où il est utilisé.

1 votes

Cela ne s'applique pas vraiment, car vous ne pouvez pas accéder aux variables d'instance de la classe englobante en C# comme vous le pouvez en Java. Seuls les membres statiques sont accessibles.

5 votes

Cependant, si vous passez une instance de la classe encapsulante dans la classe imbriquée, la classe imbriquée a un accès complet à tous les membres via cette variable d'instance... donc en fait, c'est comme si Java rendait la variable d'instance implicite, tandis qu'en C#, vous devez la rendre explicite.

0 votes

@Alex Non, en Java la classe imbriquée capture en réalité l'instance de la classe parent lors de son instanciation - entre autres choses, cela signifie que cela empêche la classe parent d'être collectée par le ramasse-miettes. Cela signifie également que la classe imbriquée ne peut pas être instanciée sans la classe parent. Donc non, ce ne sont pas du tout la même chose.

10voto

kay.one Points 3498

Modèle singleton totalement fainéant et sûr pour les threads

public sealed class Singleton
{
    Singleton()
    {
    }

    public static Singleton Instance
    {
        get
        {
            return Nested.instance;
        }
    }

    class Nested
    {
        // Constructeur statique explicite pour indiquer au compilateur C#
        // de ne pas marquer le type comme étant initié avant le champ
        static Nested()
        {
        }

        internal static readonly Singleton instance = new Singleton();
    }
}

source: https://csharpindepth.com/Articles/Singleton

5voto

Chris Dail Points 11406

Cela dépend de l'utilisation. Je n'utiliserais presque jamais une classe imbriquée publique mais j'utilise tout le temps des classes imbriquées privées. Une classe imbriquée privée peut être utilisée pour un sous-objet destiné à être utilisé uniquement à l'intérieur du parent. Un exemple en serait si une classe HashTable contient un objet Entry privé pour stocker des données uniquement en interne.

Si la classe est destinée à être utilisée par l'appelant (externellement), j'aime généralement la rendre une classe autonome séparée.

3voto

aku Points 54867

Si j'ai bien compris l'article de Katheleen, elle propose d'utiliser des classes imbriquées pour pouvoir écrire SomeEntity.Collection au lieu de EntityCollection. À mon avis, c'est une manière controversée d'économiser de la frappe. Je suis presque certain qu'en application réelle, les collections auront quelques différences dans les implémentations, donc vous devrez créer une classe séparée de toute façon. Je pense que l'utilisation du nom de classe pour limiter la portée d'autres classes n'est pas une bonne idée. Cela pollue l'intellisense et renforce les dépendances entre les classes. L'utilisation des espaces de noms est une façon standard de contrôler la portée des classes. Cependant, je trouve que l'utilisation de classes imbriquées comme dans le commentaire de @hazzen est acceptable à moins que vous n'ayez des tonnes de classes imbriquées, ce qui est un signe de conception médiocre.

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