12
votes

Visibilité du constructeur de classe imbriquée

Y a-t-il un moyen de limiter l'instanciation de la classe imbriquée en C #? Je souhaite empêcher la classe imbriquée d'être instanciée d'une autre classe, à l'exception de la classe de nidification, mais de permettre un accès complet à la classe imbriquée à partir d'un autre code.


4 commentaires

On dirait que vous réinventez le modèle de conception singleton.


@ Bastiaan: Vous voulez dire implémenter . Vous ne réinventez pas de modèles de conception ....


Déclarez des membres que vous ne voulez pas être accessible, y compris le constructeur, interne. C'est la valeur par défaut.


Problème avec interne est qu'il laisse toujours ces membres accessibles à d'autres types de l'assemblage. Ce qui a besoin C # est une visibilité "parent" qui permet uniquement l'accès du type enfermé le type imbriqué.


6 Réponses :


34
votes

Habituellement, je crée une interface pour la fonctionnalité que vous souhaitez exposer à d'autres classes, puis effectuez la classe imbriquée privée et implémenter cette interface. De cette façon, la définition de classe imbriquée peut rester cachée: xxx


0 commentaires

6
votes

En bref, non, vous ne pouvez pas faire ça. Il y a un modificateur d'accessibilité "public" qui signifie "accessible par n'importe quoi en moi ou en dehors de moi" et il y a un modificateur d'accessibilité "privé" qui signifie "accessible par n'importe quoi à l'intérieur de moi". Il n'y a pas de modificateur qui signifie "accessible à la chose immédiatement à l'extérieur de moi mais pas à rien d'autre que", c'est ce que vous auriez besoin de marquer le constructeur comme. Ce n'est tout simplement pas un concept que les concepteurs du système de type pensaient être utiles.

Pouvez-vous décrire pourquoi vous voulez ce type d'accessibilité folle? Peut-être qu'il y a une meilleure façon d'obtenir ce que vous voulez.


3 commentaires

Sur le dessus de ma tête (parce que c'est ma préoccupation avec cela): mettre en œuvre IAsynCreulsulte.


Faux, vois ma réponse.


@MattESPR: Bien que je trouve délicieux que vous pensiez que je me trompe d'une fonctionnalité que j'ai mise en œuvre, je vous assure que je suis correct dans mon affirmation selon laquelle il n'y a pas de modificateur d'accessibilité qui correspond à la description de l'affiche originale décrite.



4
votes

Comme il n'y a rien dans la syntaxe C #, vous devrez mettre en œuvre quelque chose comme "un contrat" ​​entre eux. Vous pouvez profiter du fait que la classe imbriquée peut accéder à des champs privés de son parent: xxx

bien sûr, vous pouvez ajuster le contrat pour gérer différents paramètres xxx


1 commentaires

Pour moi, le constructeur statique de la classe intérieure ne s'appelle pas et je reçois une nullreferenceException



6
votes

Si vous avez besoin de répondre à l'une des conditions suivantes:

  • Vous voulez que la classe imbriquée soit scellée,
  • Vous ne souhaitez pas copier toutes les signatures méthodes de la classe imbriquées à une interface comme dans La réponse de Lee ,

    J'ai trouvé une solution similaire à Celui publié par ak99372 , mais sans utiliser d'initialisateur statique: xxx

    L'idée est que le constructeur de classe imbriqué est accessible uniquement à la classe usine , qui est imbriqué un niveau Plus profond. La classe usine implémente explicitement la méthode CreateInstance à partir de l'interface privée iprivateFactory , de sorte que seuls ceux qui peuvent voir iprivatefactory peut appeler createInstance et obtenir une nouvelle instance de imbriqué .

    code en dehors de la classe externe ne peut créer librement des instances de imbriqué sans demander externe.getNEST () , car

    1. externe.Nets S est privé, ils ne peuvent donc pas l'appeler directement
    2. extérieur.NEST.Factory peut être instancié, mais ne peut pas être distribué sur iprivateFactory , donc son CreateInstance () La méthode peut ' t être appelé.

      Notez que je ne recommanderais pas d'utiliser ce modèle fortement dans le code de production, mais c'est une astuce que je trouve utile d'avoir ma manche à des occasions rares.


0 commentaires

2
votes

Pour la réponse proposée par Joshua Smith, j'ai constaté nécessaire de forcer le constructeur statique de ClassClass à courir, réalisé en appelant une méthode d'IVIALISATION STATIQUE () vide sur une classe d'amis du constructeur statique de parentclass.


1 commentaires

Vous devriez commenter la réponse de Joshua plutôt que de poster une nouvelle réponse qui n'est pas vraiment une.



0
votes
public class Outer
{
    public class Nested
    {
        readonly Outer Outer;

        public Nested(Outer outer /* , parameters */)
        {
            Outer = outer;

            // implementation
        }

        // implementation
    }

    public Nested GetNested(/* parameters */) => new Nested(this /* , parameters */);
}
Note that you can access private members of Outer from Nested.

0 commentaires