代码之家  ›  专栏  ›  技术社区  ›  sventevit

为什么resharper建议使用只读字段

  •  11
  • sventevit  · 技术社区  · 16 年前

    为什么在我下面的示例中,ReSharper建议“设置”的只读字段?

    readonly 修饰符,如果您仅在构造函数中更改此字段,但在我的示例中,我也在同一类中的另一个方法中更改它。

    public partial class OptionsForm : Form
    {
        private Settings settings;
    
        public OptionsForm(Settings s)
        {
            settings = s;
        }
    
        private void SaveData()
        {
            settings.ProjectName = TextBoxProject.Text;
        }
    }
    
    7 回复  |  直到 14 年前
        1
  •  27
  •   Noffls    13 年前

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

    • 可以初始化引用类型数据成员以指向 类的实例,但一旦完成,就不可能使其 指向构造函数之外的类的另一个实例
    • 只读修改器对只读数据成员的对象没有影响 指向。

    阅读一篇关于这方面的详细文章

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

        2
  •  5
  •   Ian Ringrose    16 年前

    通过将字段标记为只读 你正在告诉全班的读者 不需要考虑 怎样

    读者(例如一个人) 你的设计与否。

    如果字段指向的对象中的值在对象生存期内发生变化,那么我认为字段不应标记为只读。(例如,指向的对象的行为应在调用类中的承包商时保持不变)

    (但是也有一些例外情况,例如,即使记录器确实更改了日志文件的状态,也可以使用只读字段指向记录器。)

        3
  •  2
  •   Bob Hall    14 年前

    ReSharper建议将“设置”设置为只读:

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

    因为,在扫描代码时,它得出结论,您的“设置”字段仅出现在同一类的构造函数中。

    如果您在这个类中提供了一个修改了“设置”的分部类或其他代码,它将不再建议它是只读的。

    一旦标记为readonly,编译器会将字段的各种误用标记为警告,例如:

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

    这与您尝试为常量赋值时遇到的错误相同。

    还有 裁判 出来 参数修改器是有限的。

        4
  •  0
  •   Lazarus    16 年前

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

        5
  •  0
  •   Ori Shavit    16 年前

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

        6
  •  0
  •   Andriy Volkov    16 年前

    事实上,你是对的,而Resharper是错的。仅当字段的整体不可变时,才应将其标记为只读。在您的示例中,如果将其设置为只读并启用Microsoft的代码分析,它将警告您设置具有可变属性。

        7
  •  0
  •   nicodemus13    15 年前

    这似乎有点奇怪,我无法想象Eric Lippert等人没有考虑到明显的事实,使引用不可变不会使引用指向不可变的实例,尽管所提到的代码分析规则确实支持上述视图。http://msdn.microsoft.com/en-us/library/ms182302(v=VS.100).aspx)。

    这仍然没有任何意义。如果可变实例不应该是只读的,那么,在我看来,它应该是一个编译时错误,否则似乎毫无意义。