3

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?

0

3 Answers 3

2

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

Replace Constructor with Factory Method (refactoring.com)

Sign up to request clarification or add additional context in comments.

3 Comments

That works pretty well for my example. If you start adding more constructors though you end up with a lot of duplicated code (i.e. if you in reality you want chains of more than 2 constructors).
+1 If the constructor gets complicated, use separate initialization logic.
@fearofawhackplanet, can you give an example of situalition with a lot of duplicated code?
1

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.

Comments

1

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

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.