我正在为我的项目使用IoC和DI。
但是我想知道是否有好的做法是:
private readonly IMyService myservice;
作为服务使用者的类中的字段。该字段在构造函数中设置。
我确定我已经在某个地方看到了这个并且我已经接受了它。 但是我也看到了:
private IMyService myservice;
似乎就足够了。是否有任何目的为注入的服务接口提供只读字段?有什么好处?
答案 0 :(得分:10)
这是一个界面无关紧要的事实。在字段上应用readonly
修饰符可防止您(或其他人)在构造对象后更改其值。它只能在构造函数中分配。
答案 1 :(得分:7)
我认为使用readonly
关键字是构造函数注入正确实现的核心部分。
public class MyClass
{
private readonly IMyService myservice;
public MyClass(IMyService myservice)
{
if (myservice == null)
{
throw new ArgumentNullException("myservice");
}
this.myservice = myservice;
}
}
readonly
关键字和Guard子句在技术上必需来实现构造函数注入。但是,它们都有助于加强班级的不变量。 This is what encapsulation is all about
答案 2 :(得分:5)
readonly
字段表示只能在ctor中写入。一旦完成,就无法更改或销毁引用。它对于初始化状态和强制执行不变性非常有用。
答案 3 :(得分:2)
在字段上使用readonly
的优点是明确声明该字段在包含实例的生命周期内不会更改。在许多情况下,这使得更容易推断给定方法的行为。例如
void Method() {
var marker = myservice.StartOperation();
try {
SomeOtherMethod();
} finally {
myservice.StopOperation(marker);
}
}
假设StartOperation
和StopOperation
是必须在给定IMyService
实例上成对调用的方法。当myservice
是readonly
字段时,您只能查看此功能,并且对履行此合同具有高度的信心。
但是如果它不是readonly
,你必须立即怀疑SomeOtherMethod
以及从该函数传递调用的所有其他方法。如果其中任何一个突然重置myservice
字段,那么你将违反合同并最终产生一些非常微妙的错误。
答案 4 :(得分:1)
Here is the documentation for the readonly keyword.
当应用于类中的字段时,readonly
向读者表明“此字段在此实例的生命周期内不会更改。”这是非常有用的依赖项信息,在构造函数中接收它们后无意更改。
错误地尝试更改依赖项会导致编译时错误,提醒您或其他任何人正在修改注入依赖项的类不应更改。与忽略readonly
关键字以及稍后由于重新分配而必须追踪错误相比,这是一种更容易检测和修复的情况。
简而言之,是的,如果你在构造对象之后没有改变它,那么声明一些readonly
是一个好习惯,因为它会让所有未来的作者都不会犯这个错误。