Call one constructor from the body of another in C#

若如初见. 提交于 2019-12-18 12:43:35

问题


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

回答1:


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) { ... }



回答2:


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.




回答3:


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



回答4:


This is not supported - see Constructors in C#.

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




回答5:


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



回答6:


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.



来源:https://stackoverflow.com/questions/7575739/call-one-constructor-from-the-body-of-another-in-c-sharp

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!