web-dev-qa-db-fra.com

Appeler constructeur répandu et constructeur de base en C #

J'ai deux classes, foo et bar, qui ont des constructeurs comme celui-ci:

class Foo
{
    Foo()
    {
      // do some stuff
    }

    Foo(int arg)
    {
      // do some other stuff
    }
}

class Bar : Foo
{
    Bar() : base()
    {
      // some third thing
    }
}

Maintenant, je veux introduire un constructeur pour la barre qui prend un INT, mais je veux que les trucs qui se produisent dans la barre () doivent courir aussi comme les choses de FOO (int). Quelque chose comme ça:

Bar(int arg) : Bar(), base(arg)
{
  // some fourth thing
}

Y a-t-il un moyen de le faire en C #? Le meilleur que j'ai jusqu'à présent est de mettre le travail effectué par bar () dans une fonction, qui est également appelé par bar (int), mais c'est assez inélégant.

50
reilly

Non, ce n'est pas possible. Si vous utilisez un réflecteur pour examiner l'IL qui est généré pour chaque constructeur, vous verrez pourquoi - vous finiriez par appeler les deux constructeurs pour la classe de base. En théorie, le compilateur pourrait construire des méthodes cachées pour accomplir ce que vous voulez, mais il n'y a pas vraiment d'avantage sur vous faire la même chose explicitement.

24
Curt Hagenlocher

Je repentirais des constructeurs, alors ils sont appelés comme

Bar() : this(0) 
Bar(int) : Foo(int) initializes Bar
Foo(int) initializes Foo
Foo() : this(0) 

Ceci convient, si des constructeurs sans paramètre supposent une sorte de valeur par défaut pour le paramètre INT d'un autre constructeur. Si des constructeurs ne sont pas liés, vous faites probablement quelque chose de mal à votre type, ou peut-être avons-nous besoin de plus d'informations sur ce que vous essayez d'atteindre.

32
Ilya Ryzhenkov

Je recommanderais de changer votre chaîne de constructeur pour passer du moins spécifique à la plupart spécifique.

class Foo
{
    Foo()
    {
      // do some stuff
    }

    Foo(int arg): this()
    {
      // do some other stuff
    }
}

class Bar : Foo
{
    Bar() : Bar(0)
    {
      // some third thing
    }

    Bar(int arg): base(arg)
    {
      // something
    }
}

Toute création de l'objet bar sera maintenant appelera tous les 4 constructeurs. Le chaînage constructeur devrait fournir des valeurs par défaut à des constructeurs plus spécifiques, pas l'inverse. Vous devriez vraiment regarder ce que vous essayez d'accomplir et de vous assurer que ce que vous faites a du sens. Curt est juste qu'il y a des raisons techniques que vous ne pouvez pas faire cela, mais il existe également des raisons logiques pour lesquelles vous ne devriez pas.

13
NerdFury

C'est seulement une chose que je peux penser à ...

 public class Foo
{
    public Foo()
    {
    }
    public Foo(int? arg): this()
    {
    }

}
public class Bar : Foo
{
    private int x;
    public Bar(): this(new int?()) // edited to fix type ambiguity
    {
        // stuff that only runs for paramerless ctor
    }
    public Bar(int? arg)
        : base(arg)
    {
        if (arg.HasValue)
        {
            // Do stuff for both parameterless and parameterized ctor
        }
        // Do other stuff for only parameterized ctor
    }
}
4
Charles Bretana

Vous ne pouvez pas avoir le constructeur de bar qui prend un INT invoque le constructeur sans paramètre?

1
Jim Anderson

Pouvez-vous mettre les choses à partir de la barre () dans la barre (int) et la barre d'appels (int) avec barre () avec une valeur par défaut? Ensuite, la barre (int) peut appeler le constructeur de base.

class Bar : Foo
{
    Bar() : this(0)
    {
    }

    Bar(int arg) : base(arg)
    {
    }
}

Cela ne répond pas exactement à votre question, mais en fonction de votre scénario pourrait être une solution réalisable.

1
g .

pouvez-vous prendre le code d'initialisation pour la barre () et procéder à une méthode et l'appeler des constructeurs et le nouveau constructeur d'appelez-vous simplement (ARG)?

1
CSharpAtl

Vous pouvez utiliser ce code:

public Foo
{
    public Foo()
    {
        this.InitializeObject();
    }

    public Foo(int arg) : this()
    {
        // do something with Foo's arg
    }

    protected virtual void InitializeObject()
    {
        // initialize object Foo
    }
}

public Bar : Foo
{
    public Bar : base() { }

    public Bar(int arg) : base(arg)
    {
       // do something with Bar's arg
    }

    protected override void InitializeObject()
    {
       // initialize object Bar

       base.InitializeObject();
    }
}

Il suffit de remplacer la méthode InitializeObject() comme dans le code ci-dessus et mettez tout votre code que vous souhaitez mettre dans le constructeur de paramètres. Et enfin appeler base.InitializeObject() à la fin du code.

J'espère que cela est utile.

0
Moch Yusup