51

次のようなコンストラクターを持つ 2 つのクラス、Foo と Bar があります。

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

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

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

ここで、int を取る Bar のコンストラクターを導入したいと思いますが、Bar() で発生するものと Foo(int) のものを実行したいと考えています。このようなもの:

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

C#でこれを行う方法はありますか? これまでのところ、Bar() によって行われた作業を Bar(int) によっても呼び出される関数に入れるのが最善ですが、これはかなり洗練されていません。

4

8 に答える 8

32

コンストラクターを再チェーンするため、次のように呼び出されます

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

これは、パラメーターなしのコンストラクターが他のコンストラクターの int パラメーターに対して何らかのデフォルト値を想定している場合に適しています。コンストラクターが関連していない場合は、おそらく型に何か問題があるか、何を達成しようとしているのかについてさらに情報が必要な可能性があります。

于 2008-12-02T20:29:44.440 に答える
24

いいえ、これは不可能です。Reflector を使用して、コンストラクターごとに生成された IL を調べると、その理由がわかります。最終的に、基本クラスの両方のコンストラクターを呼び出すことになります。理論的には、コンパイラは目的を達成するために隠しメソッドを構築できますが、同じことを明示的に行うことに勝る利点はありません。

于 2008-12-02T20:29:00.900 に答える
13

コンストラクターチェーンを変更して、最も具体的でないものから最も具体的なものに変更することをお勧めします。

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
    }
}

Bar オブジェクトを作成すると、4 つのコンストラクターすべてが呼び出されるようになりました。コンストラクター チェーンは、より具体的なコンストラクターに既定値を提供する必要があり、その逆ではありません。自分が達成しようとしていることをよく見て、自分のしていることに意味があることを確認する必要があります。これを行うことができない技術的な理由があることは正しいですが、そうすべきではない論理的な理由もあります。

于 2008-12-02T20:33:22.763 に答える
4

これしか思い浮かばない…

 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
    }
}
于 2008-12-02T20:32:48.723 に答える
1

Bar() の内容を Bar(int) に入れ、デフォルト値で Bar() を使用して Bar(int) を呼び出すことはできますか? その後、Bar(int) は基本コンストラクターを呼び出すことができます。

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

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

それはあなたの質問に正確に答えるものではありませんが、シナリオによっては実行可能な解決策になるかもしれません。

于 2008-12-02T20:29:15.437 に答える
1

Bar() の初期化コードを取得してメソッドにし、両方のコンストラクターから呼び出して、新しいコンストラクターに base(arg) を呼び出すだけにできますか?

于 2008-12-02T20:38:29.600 に答える
1

int を取る Bar コンストラクターでパラメーターなしのコンストラクターを呼び出すことはできませんか?

于 2008-12-02T20:27:59.420 に答える
0

次のコードを使用できます。

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();
    }
}

上記のコードと同じようにメソッドをオーバーライドしInitializeObject()、パラメーターなしのコンストラクターに入れたいすべてのコードをそこに入れます。そして最後base.InitializeObject()にコードの最後で呼び出します。

これが役に立つことを願っています。

于 2013-04-30T02:45:41.113 に答える