Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Private readonly Interface - is it redundant?

I am using IoC and DI for my project.

However I was wondering if it is good practise 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?

like image 946
jaffa Avatar asked May 31 '11 15:05

jaffa


4 Answers

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.

like image 137
Thomas Levesque Avatar answered Nov 03 '22 17:11

Thomas Levesque


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.

like image 26
Mark Seemann Avatar answered Nov 03 '22 16:11

Mark Seemann


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.

like image 25
Rex M Avatar answered Nov 03 '22 17:11

Rex M


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.

like image 44
JaredPar Avatar answered Nov 03 '22 15:11

JaredPar