开发者

Private readonly Interface - is it redundant?

开发者 https://www.devze.com 2023-03-09 23:29 出处:网络
I am using IoC and DI for my project. However I was wondering if it is good pr开发者_运维知识库actise to have the following:

I am using IoC and DI for my project.

However I was wondering if it is good pr开发者_运维知识库actise to have the following:

private readonly IMyService myservice;

as the field inside the class that is a consumer of the service. The field is set in the constructor.

I'm sure I've seen this somewhere and I've picked up on it. However I also see:

private IMyService myservice;

and it seems to suffice. Is there any purpose to have a readonly field for the injected service interface? What are the advantages?


The fact that it's an interface is irrelevant. Applying the readonly modifier on a field prevents you (or someone else) to change its value after the object is constructed. It can only be assigned in the constructor.


I consider use of the readonly keyword a central part of proper implementation of Constructor Injection.

public class MyClass
{
    private readonly IMyService myservice;

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

Neither the readonly keyword nor the Guard Clause are technically required to implement Constructor Injection. However, they both help strengthen the invariants of the class. This is what encapsulation is all about.


A readonly field means it can only be written in the ctor. Once that's completed, the reference can't be changed or destroyed. It's very useful for initializing state and enforcing immutability.


The advantage of having readonly on the field is it's a clear declaration that the field will not change during the lifetime of the containing instance. In many scenarios this makes it easier to reason about the behavior of a given method. For example

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

Assume that StartOperation and StopOperation are methods which must be called in pairs on a given IMyService instance. When myservice is a readonly field you can look only at this function and have a high degree of confidence in meeting this contract.

However if it's not readonly you must be immediately suspcious of SomeOtherMethod and every other method transitively called from that function. If any of them could reset the myservice field suddenly you would be in violation of the contract and end up with some very subtle bugs.


Here is the documentation for the readonly keyword.

When applied to a field in a class, readonly indicates to the reader "this field will not change for the lifetime of this instance." That is highly useful information for dependencies, which are not intended to change after receiving them in the constructor.

A misguided attempt to alter a dependency results in a compile-time error, reminding you or whomever else is modifying the class that injected dependencies should not change. This is a much easier situation to detect and fix than omitting the readonly keyword and later having to track down a bug because of a reassignment.

In short, yes, it is good practice to declare something readonly if you do not change it after the object is constructed, as it will keep all future authors from making that mistake.

0

精彩评论

暂无评论...
验证码 换一张
取 消