私有只读接口 – 它是多余的吗?

我正在为我的项目使用IoC和DI。

但是我想知道以下是否是一个好习惯:

private readonly IMyService myservice; 

作为服务使用者的类中的字段。 该字段在构造函数中设置。

我确定我已经在某个地方看到了这个并且我已经接受了它。 但是我也看到:

 private IMyService myservice; 

这似乎就足够了。 是否有任何目的为注入的服务接口提供只读字段? 有什么好处?

我认为使用readonly关键字是构造函数注入的正确实现的核心部分。

 public class MyClass { private readonly IMyService myservice; public MyClass(IMyService myservice) { if (myservice == null) { throw new ArgumentNullException("myservice"); } this.myservice = myservice; } } 

从技术上讲, readonly关键字和Guard子句都不需要实现构造函数注入。 但是,它们都有助于加强class级的不变量。 这就是封装的全部内容 。

事实上它是一个界面是无关紧要的。 在字段上应用readonly修饰符会阻止您(或其他人)在构造对象后更改其值。 它只能在构造函数中指定。

readonly字段意味着它只能写在ctor中。 一旦完成,就无法更改或销毁引用。 它对于初始化状态和强制执行不变性非常有用。

拥有readonly on the field的优点是它清楚地声明该字段在包含实例的生命周期内不会改变。 在许多情况下,这使得更容易推断给定方法的行为。 例如

 void Method() { var marker = myservice.StartOperation(); try { SomeOtherMethod(); } finally { myservice.StopOperation(marker); } } 

假设StartOperationStopOperation是必须在给定的IMyService实例上成对调用的方法。 当myservice是一个readonly字段时,您只能查看此function,并且对满足此合同具有高度的信心。

但是,如果它不是readonly你必须立即怀疑SomeOtherMethod和从该函数传递调用的所有其他方法。 如果他们中的任何一个突然重置myservice字段你将违反合同并最终得到一些非常微妙的错误。

以下是readonly关键字的文档。

当应用于类中的字段时, readonly向读者指示“此字段在此实例的生命周期内不会更改”。 这对依赖项非常有用,在构造函数中接收它们之后无意更改。

错误的尝试更改依赖项会导致编译时错误,提醒您或其他任何人正在修改注入依赖项的类不应更改。 这比检测和修复更容易,而不是省略readonly关键字,后来由于重新分配而不得不追踪错误。

简而言之,是的,如果你在构造对象之后没有改变它,那么最好只声明一些东西,因为它会让所有未来的作者都不会犯这个错误。