2
votes

Comment exécuter une méthode dans la classe de base une fois que l'enfant est complètement initialisé?

J'ai implémenté la structure suivante:

public abstract class A
{
    protected A()
    {
        Test();
    }

    private void Test()
    {
        Console.WriteLine("2");
    }
}

public class B : A
{
    public B() : base()
    {
        Console.WriteLine("1");
    }
}

Lorsque je crée une instance de la classe B , la méthode Test () est exécutée avant que le constructeur n'appelle dans la classe B . Dans mon cas, cette méthode doit s'exécuter une fois que l'enfant est complètement initialisé. Une façon possible de le faire fonctionner serait de rendre Test () accessible depuis B et de l'appeler à la fin de son constructeur. Cela fonctionnerait mais si quelqu'un crée une autre sous-classe de A , il y a une chance qu'il oublie d'appeler la méthode. Ma question est de savoir s'il existe une solution plus générale dans la classe de base pour s'assurer que la méthode est exécutée après l'initialisation complète d'un enfant.


1 commentaires

C'est une demande courante. Il n'y a aucune installation pour cela dans le runtime .NET ou le langage C #.


3 Réponses :


2
votes

La réponse est non.

Il n'y a rien de intégré dans .NET ou C # qui puisse garantir que les méthodes sont appelées après que tous les constructeurs descendants ont été exécutés.

Une approche différente serait une forme de modèle d'usine, où votre classe vous fournirait simplement une autre instance correctement configurée et toutes les méthodes requises appelées.


0 commentaires

2
votes

Cela ne peut pas être fait car l'initialiseur du constructeur ne fonctionne pas de cette façon. Vous pouvez plutôt choisir de passer un paramètre au constructeur de base, des paramètres qui peuvent être spécifiques à votre classe enfant comme

public abstract class A
{
    protected A(string data)
    {
        Test(data);
    }

    private void Test(string data)
    {
        Console.WriteLine(data);
    }
}

public class B : A
{
    public B() : base("1")
    {
        //some other initialization logic here
    }
}


1 commentaires

Il peut s'agir d'un délégué, qui est appelé avant Test () et contient une initialisation spécifique à la classe héritée. Ensuite, le constructeur de classe hérité peut être laissé vide. Mais certaines fonctionnalités (par exemple, définir la valeur sur les propriétés automatiques de lecture uniquement) ne fonctionneront pas.



1
votes

Vous ne pouvez pas directement "insérer" un appel de méthode avant d'appeler le constructeur de la classe de base, car il appelle une méthode sur un objet non initialisé. Mais vous pouvez utiliser le modèle de méthode de modèle:

1
2

Vous pouvez également rendre la méthode Test virtuelle:

abstract class A {

    protected A () {
        Test ();
    }

    protected virtual void Test () {
        Console.WriteLine ("2");
    }

}


class B : A {

    protected override void Test () {
        Console.WriteLine ("1");
        base.Test ();
    }

}


internal class Program {

    public static void Main (string [] args) {
        new B ();
    }

}

Les deux exemples donnent le même résultat:

abstract class A {

    protected A () {
        BeforeTest ();
        Test ();
    }

    protected abstract void BeforeTest ();

    private void Test () {
        Console.WriteLine ("2");
    }

}


class B : A {

    protected override void BeforeTest () {
        Console.WriteLine ("1");
    }

}


internal class Program {

    public static void Main (string [] args) {
        new B ();
    }

}


0 commentaires