专用只读接口-它是多余的吗

本文关键字:多余 只读 接口 专用 | 更新日期: 2023-09-27 17:57:59

我的项目使用IoC和DI。

然而,我想知道拥有以下内容是否是一种好的做法:

private readonly IMyService myservice;

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

我确信我在某个地方见过这个,而且我已经学会了。然而,我也看到:

private IMyService myservice;

这似乎就足够了。为注入的服务接口设置只读字段有什么用途吗?优点是什么?

专用只读接口-它是多余的吗

它是一个接口这一事实无关紧要。在字段上应用readonly修饰符可以防止您(或其他人)在构造对象后更改其值。它只能在构造函数中分配。

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

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

readonly关键字和Guard子句在技术上都不需要来实现构造函数注入。然而,它们都有助于增强类的不变量。这就是封装的意义所在。

readonly字段表示只能在ctor中写入。一旦完成,引用就不能更改或销毁。它对于初始化状态和增强不变性非常有用。

在字段上具有readonly的优点是它清楚地声明了字段在包含实例的生存期内不会更改。在许多场景中,这使得对给定方法的行为进行推理变得更容易。例如

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

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

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

这是readonly关键字的文档。

当应用于类中的字段时,readonly向读取器指示"此字段在该实例的生存期内不会更改。"这对于依赖关系是非常有用的信息,在构造函数中接收到依赖关系后,这些依赖关系不会更改。

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

简言之,是的,如果在构建对象后不更改readonly,那么声明它是一种很好的做法,因为这将防止所有未来的作者犯这个错误。