I have the following situtation with overloaded constructors which I'm struggling to find a nice solution to. I can't see how to use an intermediate assignment with constructor chaining.
The following isn't valid but shows what I want to do
public MyThing(IServiceLocator services, int? userId)
{
// blah....
}
public MyThing(IServiceLocator services, string userName)
{
User user = services.UserService.GetUserByName(userName);
int userId = user == null ? null : (int?)user.Id;
// call the other constructor
this(services, userId);
}
The only way I know to write the above in valid code is
public MyThing(IServiceLocator services, string userName)
: this(services,
services.UserService.GetUserByName(userName) == null ?
null : (int?)services.UserService.GetUserByName(userName).Id)
which is not only ugly code, but also requires the database call twice (unless the compiler is clever enough to work that out, which I doubt).
Is there a better way to write the above?
What about this:
public MyThing(IServiceLocator services, string userName)
{
User user = services.UserService.GetUserByName(userName);
int? userId = user == null ? null : (int?)user.Id;
Initialize(services, userId);
}
public MyThing(IServiceLocator services, int? userId)
{
Initialize(services, userId);
}
private void Initialize(IServiceLocator services, int? userId)
{
// initialization logic
}
EDIT
If I were you I'd replace constructor with factory method like this:
private MyThing(IServiceLocator services, int? userId)
{
// blah....
}
public static Create(IServiceLocator services, int? userId)
{
return new MyThing(services, userId);
}
public static Create(IServiceLocator services, string userName)
{
User user = services.UserService.GetUserByName(userName);
int userId = user == null ? null : (int?)user.Id;
return new MyThing(services, userId);
}
Usage:
var myThing = MyThing.Create(services, 123);
var myOtherThing = MyThing.Create(services, "userName");
There is, yes. I know that the example is in Java but it's such a nice solution to your problem that some effort of porting to C# does make sense.
You can use a static helper method:
public MyThing(IServiceLocator services, int? userId)
{
// blah....
}
public MyThing(IServiceLocator services, string userName)
: this(services, GetUserId(services, userName))
{
}
private static int? GetUserId(IServiceLocator services, string userName)
{
User user = services.UserService.GetUserByName(userName);
return (user == null) ? (int?)null : user.Id;
}
来源:https://stackoverflow.com/questions/4376187/constructor-chaining-with-intermediate-variables