Constructor chaining with intermediate variables

那年仲夏 提交于 2019-12-22 10:46:22

问题


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?


回答1:


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)




回答2:


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.




回答3:


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

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