开发者

Call one constructor from the body of another in C#

I need to call one constructor from 开发者_运维问答the body of another one. How can I do that?

Basically

class foo {
    public foo (int x, int y)
    {
    }

    public foo (string s)
    {
        // ... do something

        // Call another constructor
        this (x, y); // Doesn't work
        foo (x, y); // neither
    }
}


You can't.

You'll have to find a way to chain the constructors, as in:

public foo (int x, int y) { }
public foo (string s) : this(XFromString(s), YFromString(s)) { ... }

or move your construction code into a common setup method, like this:

public foo (int x, int y) { Setup(x, y); }
public foo (string s)
{
   // do stuff
   int x = XFromString(s);
   int y = YFromString(s);
   Setup(x, y);
}

public void Setup(int x, int y) { ... }


this(x, y) is right, but it has to be before the start of the constructor body:

public Foo(int x, int y)
{
    ...
}

public Foo(string s) : this(5, 10)
{
}

Note that:

  • You can only chain to one constructor, either this or base - that constructor can chain to another one, of course.
  • The constructor body executes after the chained constructor call. There is no way to execute the constructor body first.
  • You can't use this within the arguments to the other constructor, including calling instance methods - but you can call static methods.
  • Any instance variable initializers are executed before the chained call.

I have a bit more information in my article about constructor chaining.


To call both base and this class constructor explicitly you need to use syntax given below (note, that in C# you can not use it to initialize fields like in C++):

class foo
{
    public foo (int x, int y)
    {
    }

    public foo (string s) : this(5, 6)
    {
        // ... do something
    }
}

//EDIT: Noticed, that you've used x,y in your sample. Of course, values given when invoking ctor such way can't rely on parameters of other constructor, they must be resolved other way (they do not need to be constants though as in edited code sample above). If x and y is computed from s, you can do it this way:

public foo (string s) : this(GetX(s), GetY(s))


This is not supported - see Constructors in C#.

However, you can implement a common (private) method which you call from the different constructors...


I've ran into this problem a time or two myself... I ended up having to extract whatever logic I needed in that other constructor into a private void method and calling it in both places.

class foo
{
  private void Initialize(int x, int y)
  {
    //... do stuff
  }

  public foo(int x, int y)
  {
    Initialize(x, y);
  }

  public foo(string s_
  {
    // ... do stuff

    Initialize(x, y)
    // ... more stuff
  }
}


There is a note in description of MethodBase.Invoke in MSDN

If this method overload is used to invoke an instance constructor, the object supplied for obj is reinitialized; that is, all instance initializers are executed. The return value is null. If a class constructor is invoked, the class is reinitialized; that is, all class initializers are executed. The return value is null.

I.e. you can get Constructor's method by reflection and call it through Invoke in your new constructor's body. But I haven't try it. And, of course, this solution have a lot of drawbacks.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜