是否只能标记一个私有字段?

时间:2011-07-12 15:35:49

标签: c# private readonly

public class Foo
{
    private readonly Bar _bar;
}

public class Foo2
{
    private Bar _bar;
}

我认为将其标记为只读没有任何好处。它是私人的,如果我尝试在内部做一些修改它,那我是愚蠢的,因为我知道我希望我的班级表现如何?那么,有什么意义呢?我不认为这里有任何性能提升,所以不可能。

6 个答案:

答案 0 :(得分:19)

让编译器阻止你变得愚蠢总是很好。

让编译器阻止其他人变得愚蠢是特别好的,即使他们不熟悉代码库。

它还可以告诉其他人阅读您的代码,该字段永远不会改变

答案 1 :(得分:4)

在您编写此课程时,您知道自己希望它如何表现。

可是:

  • 当你第一次上课时,你可能会犯错误。
  • 当你以后回来修改课程时,你可能不记得你的意图了。
  • 另一位程序员在稍后修改课程时可能不知道你的意图。

您的声明允许编译器验证您的意图是否满足,廉价且重复。并且它与您和其他人沟通您的意图。

答案 2 :(得分:2)

你是对的,没有性能提升。但是,这里有一些关键的区别:

如果您打算创建一个不尝试修改_bar的类,那么它应该是一个只读字段。我可以在这里看到两件事:

  1. 只读字段只能在内联或构建期间(安全)初始化。
  2. 它防止其他程序员出现并想“哦,它不是只读的。我可以修改它。”
  3. 现在,如果你打算将它保持为空,那么它应该只读 NOT ,直到调用另一个方法来初始化它。但是,为此,我会看Lazy<T>


    基本上,这是你的电话。如果你真的要成为 ONLY 修改这个课程,我仍然会说遵循这些规则。这是实践它的最佳实践方式。 :)

答案 3 :(得分:1)

如果你想在实例化时分配它,那么Readonly是好的,但不希望它可以改变。我能想到的一个好方案可能是一个带有用户名/密码的数据库类。

public MyClass(string user, string password){
  this.username = username;
  this.password = password;
  this.connect();
}

假设连接在整个持续时间内保持对象处于活动状态,那么存储此信息以供参考可能是有意义的,但是一旦建立连接就会阻止将来的更改。

答案 4 :(得分:1)

假设一个类应该包含一组可更改的T,并且它有一个私有字段T[] theArray。可以通过多种方式设置课程:

  1. 该字段可能是一个永远不会改变的数组的可变引用;对列表的更改将通过创建适当大小的新数组,将数据复制到其中,根据需要进行修改,然后将对新数组的引用存储到字段中来实现。注意,通过将数组包装在`ReadOnlyCollection`中,该类可以低成本地公开数组内容的只读快照。创建快照不需要复制数组。
  2. 该字段可能是对可变数组的可变引用。大多数更新都是通过改变现有数组来完成的,但是超出数组末尾的更新会创建一个新元素,其中元素将从旧数组中复制。这就是`List`的工作原理。请注意,将数组包装在`ReadOnlyCollection`中可能会产生一些内容,这些内容在一段时间内会作为实时数据的只读视图,但可能在某个任意未来时间成为当时数据的快照。
  3. 如果数组足够大以容纳将要添加的所有内容,那么该字段可能是对可变数组的不可变引用。不太可能使用可变长度列表,但在某些应用程序中,为最大项目数预先指定和预分配空间可能是合理的。在这种情况下,将数组包装在`ReadOnlyCollection`中将生成其状态的实时视图。

这三种不同的方法对线程安全等问题有不同的含义。如果readref-copy-modify-writeref序列放在Interlocked.CompareExchange循环中,则第一个可以成为线程安全的。通过使单个元素写入线程安全,可以使最后一个成为线程安全的。但是,第二个只能通过所有写入操作共享一个整体列表共用的锁定并且要求读者仔细检查其操作以确保一致性,或者要求其具有线程安全性。所有读写访问都必须通过一个公共锁。

答案 5 :(得分:0)

  

它是私人的,如果我尝试在内部做一些修改它,那我就是愚蠢,因为我知道我希望我的班级表现如何?

如果您是唯一一个在项目历史中会查看或修改源代码并且您拥有完美记忆的人,那么,是的。无需评论或其他编程约定。只是牛仔吧。

否则,使用约定(重新)强制执行意图并不是一个坏主意。