为什么ReSharper会在下面的示例中为“设置”建议只读字段?
如果我理解正确,如果仅在构造函数中更改此字段,则应使用readonly
修饰符,但在我的示例中,我也在同一类中的另一个方法中更改它。
我错过了什么?
public partial class OptionsForm : Form
{
private Settings settings;
public OptionsForm(Settings s)
{
settings = s;
}
private void SaveData()
{
settings.ProjectName = TextBoxProject.Text;
}
}
答案 0 :(得分:25)
当引用类型声明为readonly时,指针是不可变的,但不是它指向的对象。这意味着:
- 可以初始化引用类型数据成员以指向 一个类的实例,但是一旦完成,它就不可能成功 指向构造函数之外的另一个类实例
- readonly修饰符对readonly数据成员的对象没有影响 指着。
阅读关于此
的详细文章答案 1 :(得分:4)
请记住,编码标准和设计模式的主要原因是让人们更容易理解您的代码。
将字段标记为“只读”您 告诉读者这堂课 他们不需要考虑如何 该字段的值已更改。
然而,由于只读字段指向的对象可以使其状态发生变化,因此将字段标记为只读可能会产生误导。因此,考虑一下天气,它可以帮助读者(例如一个人)代码了解您的设计与否。
如果字段指向的对象中的值在对象生存期内发生变化,那么我认为字段不应该标记为只读。 (例如,指向的对象应该表现得好像在你的班级上的承包商被召唤时它是不可变的)
(但是有一些例外,例如,即使记录器确实更改了日志文件的状态,也可以使用只读字段指向记录器。)
答案 2 :(得分:2)
ReSharper建议只读“设置”:
readonly private Settings settings;
public OptionsForm(Settings s)
{
settings = s;
}
因为,在扫描你的代码时,它得出的结论是你的“settings”字段只出现在同一个类的构造函数中。
如果你要在这个类中提供一个修改“设置”的部分类或其他代码,那么它将不再表示它是只读的。
一旦标记为只读,编译器将标记为警告各种字段的错误,例如:
The left-hand side of an assignment must be an l-value
当您尝试将值分配给常量时,会出现同样的错误。
ref 和 out 参数修饰符的使用也是有限的。
通过遵循ReSharpers建议,如果您尝试滥用初始化后确实不想更改的字段,编译器会发出警告。
答案 3 :(得分:0)
您没有更改构造函数之外的设置,该对象与SaveData中的对象相同。对象属性可能正在改变,但不是对象引用,因此从Resharper角度来看似乎有意义。
答案 4 :(得分:0)
SaveData()方法不会更改设置变量,它会更改其属性。设置的内容(它引用的内容)仅在构造函数中设置。
答案 5 :(得分:0)
实际上,你是对的,而且Resharper是错的。如果字段完全不可变,则只应标记为只读字段。在您的示例中,如果您只读它并启用Microsoft的代码分析,它将警告您Settings具有可变属性。
答案 6 :(得分:0)
这似乎有点奇怪,我无法想象Eric Lippert等人,并没有考虑这样一个显而易见的事实:使引用不可变不会使引用不可变引用实例,尽管提到的代码分析规则确实支持上述视图(http://msdn.microsoft.com/en-us/library/ms182302(v = VS.100).aspx)。
它仍然没有任何意义。如果可变实例不应该是readonly,那么,在我看来,它应该是一个编译时错误,否则看起来毫无意义。
我可以看到使用引用不可变,而不是它指向的实例。