不变性

不可变性在函数式编程中很常见,在面向对象编程中很少见。

例如,创建一个具有可变状态的地址类型:

public class Address () 
{
    public string Line1 { get; set; }
    public string Line2 { get; set; }
    public string City  { get; set; }
}

任何代码都可以改变上述对象中的任何属性。

现在创建不可变的地址类型:

public class Address () 
{
    public readonly string Line1;
    public readonly string Line2;
    public readonly string City;

    public Address(string line1, string line2, string city) 
    {
        Line1 = line1;
        Line2 = line2;
        City  = city;
    }
}

请记住,拥有只读集合并不尊重不变性。例如,

public class Classroom
{
    public readonly List<Student> Students;
    
    public Classroom(List<Student> students)
    {
        Students = students;
    }
}

不是不可变的,因为对象的用户可以改变集合(从中添加或删除元素)。为了使它不可变,人们要么使用像 IEnumerable 这样的接口,它不公开要添加的方法,要么使它成为 ReadOnlyCollection。

public class Classroom
{
    public readonly ReadOnlyCollection<Student> Students;

    public Classroom(ReadOnlyCollection<Student> students)
    {
        Students = students;
    }
}

List<Students> list = new List<Student>();
// add students
Classroom c = new Classroom(list.AsReadOnly());   

使用不可变对象,我们有以下好处:

  • 它将处于已知状态(其他代码无法更改)。
  • 它是线程安全的。
  • 构造函数提供了一个验证位置。
  • 知道无法更改对象使代码更容易理解。