问题
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
thisorbase- 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
thiswithin 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