不變性

不可變性在函數語言程式設計中很常見,在物件導向程式設計中很少見。

例如,建立一個具有可變狀態的地址型別:

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());   

使用不可變物件,我們有以下好處:

  • 它將處於已知狀態(其他程式碼無法更改)。
  • 它是執行緒安全的。
  • 建構函式提供了一個驗證位置。
  • 知道無法更改物件使程式碼更容易理解。