2009-10-14 2 views
10

Почему ReSharper предлагает поле для чтения для 'настроек' в моем примере ниже?Почему resharper предлагает поля только для чтения

Если я правильно понимаю, вы должны использовать модификатор readonly, если вы изменяете это поле только в конструкторе, но в моем примере я также изменяю его другим методом в том же классе.

Что мне не хватает?

public partial class OptionsForm : Form 
{ 
    private Settings settings; 

    public OptionsForm(Settings s) 
    { 
     settings = s; 
    } 

    private void SaveData() 
    { 
     settings.ProjectName = TextBoxProject.Text; 
    } 
} 
+1

Хорошо, и как отключить это? Я не мог найти в вариантах ... – andrecarlucci

ответ

24

Если ссылочный тип объявлен как readonly, указатель является неизменным, но не объектом, на который он указывает. Это означает, что:

  • член данных ссылочного типа может быть инициализирован для того, чтобы указать на экземпляр класса, но как только это будет сделано, это не возможно сделать это точку на другой экземпляр класс за пределами конструкторов
  • модификатор readonly не влияет на объект, на который указывает только член данных с readonly .

Читайте подробную статью об этом

Mark a C# class data member as readonly when it’s read only

+1

Как это ответить на вопрос: «Почему ReSharper предлагает поле для чтения для« настроек »в моем примере ниже?» ? – zvolkov

+0

Ссылка, указанная в приведенном выше ответе, не работает. Я думаю, что он перенесен на http://www.developer-corner.com/2009/01/mark-c-class-data-member-as-readonly.html – Raghav

+0

Я согласен с @zvolkov. Объясняется ли это ссылкой? Если да, перефразируйте ссылку здесь. – jcollum

0

Вы не изменяете настройки вне конструктора, объект тот же, что и в SaveData. Свойства объекта могут меняться, но не ссылки на объекты, поэтому, похоже, это имеет смысл с точки зрения Resharper.

0

Метод SaveData() не изменяет переменную настроек, она меняет один из ее свойств. Содержимое настроек (к чему это относится) устанавливается только в конструкторе.

4

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

Выделив поле, как «только для чтения» вы говорят читателю класса , что они не нужно рассматривать как значение поля изменяется.

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

Если значения в объекте, которое поле указывает на изменения в течение жизни объекта, я не думаю, что поле должно быть помечено только для чтения. (Например, указанный объект должен вести себя так, как если бы он был неизменным к тому времени, когда был вызван подрядчик в вашем классе)

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

+0

Итак, вы предполагаете, что в моем случае модификатор 'readonly' просто смутил бы читателя? – sventevit

+0

@simon, да, так как значения в настройках меняются, я бы не стал его читать только. –

+0

Я не думаю, что это хорошая интерпретация. Модификатор readonly делает ссылку неизменной, она имеет конкретные применения; то, что говорит ваш блочный комментарий, совсем не прав. Кроме того, почему вы решили, что регистратор является приемлемым специальным случаем? – nicodemus13

0

На самом деле, вы правы, а Resharper ошибается. Поле следует указывать только для чтения, если оно является неизменным во всей полноте.В вашем примере, если вы сделаете это только для чтения и включите анализ кода Microsoft, он предупредит вас, что настройки имеют изменяемые свойства.

+0

Неправда. Я предлагаю вам посмотреть http://msdn.microsoft.com/en-us/library/acdd6hb7%28VS.71%29.aspx – blowdart

+0

Blowdart, ваша ссылка MSDN определяет поведение ключевого слова/компилятора, не вдаваясь в спецификацию значения типы противссылочных типов, а также не рассматривая SEMANTICS ключевого слова. Теперь ключевое слово отлично работает для типов значений (и неизменяемых ссылочных типов), но имеет интересные последствия для изменяемых типов ссылок. Скажем, поле является хэш-таблицей. Пометяет поле, как только что сделать хэш-таблицу неизменным? Нет! Вы не можете изменить указатель, чтобы указать на другую хеш-таблицу, но вы STILL можете изменить данные. Вот почему вы не должны использовать его в изменяемых ссылочных типах. – zvolkov

0

Это, кажется, немного странно, я не могу себе представить, что Эрик Липперт и др. Не считали очевидным фактом, что создание ссылки неизменяемой не приводит к тому, что экземпляр, на который указывает эта ссылка, неизменен, хотя упомянутый Правило анализа кода поддерживает представление выше (http://msdn.microsoft.com/en-us/library/ms182302(v=VS.100).aspx).

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

Я вижу, как использование ссылки является неизменяемой, а не экземпляром, на который указывает.

1

ReSharper предлагает сделать «настройка» только для чтения:

readonly private Settings settings; 

public OptionsForm(Settings s) 
{ 
    settings = s; 
} 

потому, что при сканировании кода он делает вывод, что ваше поле «Настройка» происходит только в конструкторе для этого же класса.

Если вы хотите предоставить частичный класс или какой-либо другой код этого класса, который изменил «настройки», он больше не будет предлагать, чтобы он был только для чтения.

После отмечен только для чтения компилятор пометит как предупреждения различных злоупотреблений на местах, таких как:

The left-hand side of an assignment must be an l-value 

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

также использование ref и out Ограничители параметров ограничены.

Следуя предложению ReSharpers, вы будете предупреждены компилятором, если вы попытаетесь неправильно использовать поле, которое вы действительно не собираетесь изменять после инициализации.

Смежные вопросы