2009-10-14 83 views
10

为什么ReSharper在下面的示例中为'设置'建议readonly字段?为什么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 2010-08-11 13:57:33

回答

24

当引用类型声明为只读时,指针是不可变的,但不是它指向的对象。这意味着:

  • 引用类型的数据成员可以以点带面一类的 实例进行初始化,但是一旦做到这一点是不可能的,使其 点的另一个实例在构造函数外的类
  • readonly修饰符对只读数据成员 指向的对象没有影响。

仔细阅读本

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

+1

这是如何回答这个问题的:“为什么ReSharper在下面的示例中为'设置'建议readonly字段?” ? – zvolkov 2012-03-02 16:10:44

+0

上述回复中提到的链接不起作用。我认为这是移动到http://www.developer-corner.com/2009/01/mark-c-class-data-member-as-readonly.html – Raghav 2012-07-31 18:53:13

+0

我同意@zvolkov。它是否在链接中解释?如果是这样,请在这里解释链接。 – jcollum 2012-08-27 23:13:42

0

您不更改构造函数以外的设置,该对象与SaveData中的对象相同。对象属性可能正在改变,但不是对象引用,所以从Resharper角度来看似乎是有意义的。

0

SaveData()方法不会更改设置变量,它会更改其属性。设置的内容(它指的是)只在构造函数中设置。

4

一个详细的文章记住编码标准和设计模式的主要原因是为了做出更容易为人们所理解你的代码。

通过标记字段为“只读”你 告诉类 他们不需要考虑 的字段的值是如何被改变的读者。

但是,只读字段指向的对象可以使其状态发生更改,因此将字段标记为只读可能会引起误解。因此,想一想天气有助于读者(例如某人)的代码了解您的设计与否。

如果字段指向的对象中的值在对象生存期内发生更改,那么我认为字段不应该标记为只读。 (例如,指向的对象应该表现得好像它在你的类上的承包商被调用时是不可变的)

(但是也有一些例外,例如,使用只读字段指向记录器甚至认为记录器确实会改变日志文件的状态。)

+0

所以你建议在我的例子中'readonly'修饰符会让读者感到困惑? – sventevit 2009-10-15 07:07:50

+0

@simon,是的,随着设置中的值发生变化,我不会将其标记为只读。 – 2009-10-15 08:24:51

+0

我不认为这是一个很好的解释。 readonly修饰符使得引用不可变,它具有特定的用途;你的blockquote说的是不对的。另外,为什么你决定记录器是一个可接受的特例? – nicodemus13 2011-04-11 14:19:06

0

其实,你是对的,Resharper是错误的。只有在整个字段不可变的情况下,该字段才应该标记为只读。在你的例子中,如果你只是只读,并启用微软的代码分析,它会警告你,设置有可变属性。

+0

不正确。我建议你看看http://msdn.microsoft.com/en-us/library/acdd6hb7%28VS.71%29.aspx – blowdart 2009-10-15 09:09:28

+0

Blowdart,你的MSDN链接定义了关键字/编译器的行为,而没有进入具体的值类型vs.参考类型,也不考虑关键字的语义。现在,关键字对于值类型(以及不可变引用类型)来说工作得非常好,但对于可变引用类型有着有趣的含义。假设该字段是散列表。将该字段标记为只读,使得hashtable不可变?没有!你不能改变指针指向另一个散列表,但你仍然可以改变数据。这就是为什么你不应该在可变引用类型上使用它。 – zvolkov 2010-08-26 20:29:50

0

这似乎有点奇怪,我无法想象Eric Lippert等人并没有考虑这样一个显而易见的事实,即使参考不可变并不会使参考实例指向不可变的实例,尽管前面提到代码分析规则确实支持上述视图(http://msdn.microsoft.com/zh-cn/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 

这是你得到同样的错误,当您试图分配一个值恒定。

也使用参考参数修饰符是有限的。

通过遵循ReSharpers建议,如果您尝试滥用您在初始化后确实不想更改的字段,编译器会警告您。