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
orbase
- 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.
精彩评论