1

如果我有一个只有只读字段的 C# 类,但字段的类型不是不可变的,那么该类是否被认为是不可变的?

这个类是不可变的吗?

public class Foo
{
    private readonly int[] _blah;

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

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

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

那么,如果一个类的字段都是只读的,那么它是不可变的,还是只有当它的字段不仅是只读的,而且本身也是不可变的时,一个类才是不可变的?

4

4 回答 4

1

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

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

在您的情况下,对象是整​​数(不可变),但您的数组本身不是(再次,取决于您定义为不可变的内容)。如果您只想保证私有字段不能更改并且不关心索引,那么您就可以了。但是,如果您希望索引被锁定,那么您需要以另一种方式公开您的数组。


此外,一个不错的收藏是ReadOnlyCollection<T>. 它是一个包含对原始集合的引用(它包装它)的集合,因此不能更改索引。


另外,以防万一……对于“不可变”的实际含义,您已经有了不同的答案。

于 2013-02-13T02:45:12.673 回答
1

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

于 2013-02-13T02:48:18.000 回答
0

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

于 2013-02-13T02:42:23.353 回答
0

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

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

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

于 2013-02-13T02:50:22.503 回答