所以,我reading an article at the moment,我遇到了一些让我质疑它的代码。
代码如下所示:
private UserService _userService = null;
protected UserService UserService
{
get { return _userService ?? Request.GetOwinContext().GetUserManager<UserService>(); }
}
对我来说,私有属性看起来总是为null,因此使用null-coalescing运算符是没用的。 我认为这样做很有用:
protected UserService UserService
{
get { return Request.GetOwinContext().GetUserManager<UserService>(); }
}
我错过了什么吗?虽然我们在讨论这个问题,但为什么会这样:
private UserService _userService = null;
肯定和
相同private UserService _userService;
请帮我澄清一下我的怀疑:D
答案 0 :(得分:6)
你是对的,私有财产在你的例子中总是为空。
解决问题的一种方法是使用以下代码:
private UserService _userService = null;
protected UserService UserService
{
get
{
return _userService ?? (_userService = Request.GetOwinContext().GetUserManager<UserService>());
}
}
这样,私有属性在非null时使用,或者初始化为指定的值。执行空合并运算符??
之后的语句时,属性实际返回_userService
的赋值。
答案 1 :(得分:1)
采用这种方法并不罕见,但通常它带有参数化构造函数,如:
public class X
{
private UserService _userService = null;
protected UserService UserService
{
get { return _userService ?? Request.GetOwinContext().GetUserManager<UserService>(); }
}
public X() { }
public X(UserService svc) { _userService = svc; }
或其他一些填充服务方法的方法,如方法:
public void SetUserService(UserService svc) { _userSErvice = svc; }
使用像Moq或Rhino.Mocks这样的模拟框架,使用模拟的UserService服务构建的好处。
答案 2 :(得分:0)
我在这里加上我的两分钱:
一个可能的原因是开发人员希望创建使用readonly
字段值的_userService
属性,如果它仅由用户(di容器)分配,并且如果它不是只需从Identity
值提供程序返回值(很可能此提供程序每个http上下文使用单例)。
一般来说,我有点不喜欢在属性的getter
方法中分配字段值,因为setter
仅出于此目的而存在。
如果我们想要在代码中更改某些内容,以便以正常方式使其变得更加“正常”。我们可以在构造函数中设置此字段并向其添加可选参数:
private UserService _userService;
protected UserService UserService
{
get
{
return _userService;
}
}
public MyController(UserService service = null)
{
this._userService = service ??
Request.GetOwinContext().GetUserManager<UserService>();
}
现在代码更可测试且整洁。它还允许我们使用DI框架。这种方法的唯一缺点是我们远离延迟加载。好吧,我们可以再次使用Lazy<T>
:
private Lazy<UserService> _userService;
protected UserService UserService
{
get
{
return _userService.Value;
}
}
public MyController(UserService service = null)
{
service = service ??
Request.GetOwinContext().GetUserManager<UserService>();
_userService = new Lazy<UserService>(service);
}
现在我们可以更轻松地对代码进行单元测试,我们可以使用DI框架并从使用延迟加载中受益。
P.S。
明确地将null
值分配给引用类型字段对我来说没有多大意义。我能想到的唯一原因是它略微提高了可读性,但这似乎完全基于意见。
答案 3 :(得分:0)
如@Rob在评论中所述,这是正常模式
get { return _userService ?? _userService = Request.GetOwinContext().GetUserManager<UserService>(); }
C#8添加了null-coalescing assignment operator,它为此模式添加了一些语法糖:
get { return _userService ??= Request.GetOwinContext().GetUserManager<UserService>(); }
这与_userService ?? _userService =
相同。