如果一个类的readonly字段不是不可变的,那么它是不可变的吗?

时间:2013-02-13 02:36:02

标签: c# immutability

如果我的C#类只包含只读字段,但字段的类型不是不可变的,那么这个类是不可变的吗?

这个类是不可变的吗?

public class Foo
{
    private readonly int[] _blah;

    public Foo(int[] blah)
    {
        _blah = blah;
    }

    public int[] Blah { get { return _blah; } }
}

_blah不是不可变的,因为我可以更改数组的成员,尽管数组成员变量永远不会改变。

那么,如果一个类是不可变的,如果它的字段都是只读的,或者只有当它的字段不仅是readonly而且是不可变的时,它是一个不可变的类吗?

4 个答案:

答案 0 :(得分:1)

这实际上取决于你问的对象或你的意思。有些人可能会说类本身是不可变的,因为它的直接成员是不可变的。有些人可能会说类及其所有成员(及其属性等) - 基本上是整个对象图 - 必须是不可变的才能被认为是不可变的。

  • 标记为只读的私有字段数组是不可变的,但这并不意味着您无法使用不同的值替换索引。解决此问题的方法是返回数组的副本或数组的枚举
  • 数组的对象可能是也可能不是不可变的。无论你是让它们变成不可变还是你回复它们的克隆或其他什么,这都取决于你。

在你的情况下,对象是整​​数(它们是不可变的),但你的数组本身不是(再次,取决于你定义为不可变的)。如果您想要保证的是私有字段无法更改而且不关心索引,那么您没关系。但是,如果您希望锁定索引,那么您需要以另一种方式公开您的数组。


另外,要查看的好集合是ReadOnlyCollection<T>。它是一个集合,它包含对原始集合的引用(它包装它),因此无法更改索引。


此外,以及案件......你已经对“不可变”的实际意义的程度有不同的答案。

答案 1 :(得分:1)

此类的实例不是不可变的,因为您可以改变其内容。例如。 foo.Blah[0] = 42;。但是,如果您将Blah属性更改为IEnumerable<int>IReadOnlyList<int>,则实例将被视为不可变。

答案 2 :(得分:0)

这个类不是不可变的,因为它可以被继承并添加其他东西。

答案 3 :(得分:0)

如果它遵循三个原则,我认为它是不可变的:

  • 将字段设为私有只读。
  • 提供公共财产获取访问者。
  • 如果不再需要继承该类,请将其密封。

这些并不是严格定义不可变的硬性规则。它们只是指导方针。