Частный интерфейс только для чтения - это избыточно? - PullRequest
6 голосов
/ 31 мая 2011

Я использую IoC и DI для своего проекта.

Однако мне было интересно, если будет хорошей практикой иметь следующее:

private readonly IMyService myservice;

в качестве поля внутри класса, который являетсяпотребитель услуги.Поле задается в конструкторе.

Я уверен, что где-то видел это и поднял его.Однако я также вижу:

private IMyService myservice;

, и, кажется, этого достаточно.Есть ли цель иметь поле только для чтения для внедренного интерфейса службы?Каковы преимущества?

Ответы [ 5 ]

10 голосов
/ 31 мая 2011

Тот факт, что это интерфейс, не имеет значения. Применение модификатора readonly к полю не позволяет вам (или кому-либо еще) изменить его значение после создания объекта. Он может быть назначен только в конструкторе.

7 голосов
/ 31 мая 2011

Я считаю использование ключевого слова readonly центральной частью правильной реализации Constructor Injection.

public class MyClass
{
    private readonly IMyService myservice;

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

Ни ключевое слово readonly, ни пункт Guard не являются технически обязательными для реализации внедрения конструктора. Тем не менее, они оба помогают усиливать инварианты класса. Вот что такое инкапсуляция .

5 голосов
/ 31 мая 2011
Поле

A readonly означает, что оно может быть записано только в ctor. После этого ссылка не может быть изменена или уничтожена. Это очень полезно для инициализации состояния и обеспечения неизменности.

2 голосов
/ 31 мая 2011

Преимущество наличия readonly в поле состоит в том, что это явное заявление о том, что поле не изменится в течение времени жизни содержащего экземпляра.Во многих случаях это облегчает рассуждения о поведении данного метода.Например,

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

Предположим, что StartOperation и StopOperation являются методами, которые должны вызываться парами в данном экземпляре IMyService.Когда myservice является полем readonly, вы можете смотреть только на эту функцию и иметь высокую степень уверенности в выполнении этого контракта.

Однако, если это не readonly, вы должны немедленно подозревать SomeOtherMethod и любой другой метод, транзитивно вызванный из этой функции.Если кто-то из них сможет сбросить поле myservice внезапно, вы нарушите контракт и получите некоторые очень тонкие ошибки.

1 голос
/ 01 июня 2011

Вот документация для ключевого слова только для чтения.

При применении к полю в классе readonly указывает читателю: «Это поле не изменится в течение срока жизниэтот экземпляр. "Это очень полезная информация для зависимостей, которые не предназначены для изменения после получения их в конструкторе.

Неправильная попытка изменить зависимость приводит к ошибке во время компиляции, напоминая вам или кому-либо еще, кто изменяетКласс, который вводит зависимости, не должен меняться.Обнаружить и исправить эту ситуацию гораздо проще, чем пропустить ключевое слово readonly, а затем отследить ошибку из-за переназначения.

Короче говоря, это хорошая практика - объявлять что-либо readonly если вы не измените его после того, как объект будет сконструирован, это не позволит всем будущим авторам совершить эту ошибку.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...