iT邦幫忙

2024 iThome 鐵人賽

DAY 23
0
Software Development

程式淨化計畫:痛苦是重構的起源!系列 第 23

實作Value Type 為 Immutable物件

  • 分享至 

  • xImage
  •  

Value Type VS Reference Type

C#中, int, float, double, struct等為value type,
而由class宣告的物件稱為reference type.
由struct宣告的物件, 比如地址(Address)、座標(Point), 都是各自指一組資料.
如果它們的欄位值異動, 也代表者個物件變動了.

而class宣告的物件, 像是學生(Student)物件, 有姓名、學號、地址、電話、年級.
即使它的欄位有變化, 該學生物件仍是指它自己.

既有實作的struct有何問題

以struct宣告座標(Point):

public struct Point
{
    public int X { get; set; }
    public int Y { get; set; }
}

public class Program
{
    public void Main(string[] args)
    {
        Point p1 = new Point();
        p1.X = 1;
        p1.Y = 2;
    }
}

從上面的程式碼來看, 問題在於

  1. Point物件的X與Y都能任意修改
  2. 在多執行緒環境下, 改X與Y可能造成讀取不一致性.

將struct改為immutable

不可變(immutable)性, 是讓物件被建立後, 不能隨意更改其內部狀態.
因此, 在前面Point的宣告, 修改其constructor與property:

public struct Point
{
    public int X { get; }
    public int Y { get; }
    public Point(int x, int y) : this()
    {
        X = x;
        Y = y;
    }

    public Point Add(Point point)
    {
        return new Point(X + point.X, Y + point.Y);
    }
}

經過上面重構, 我們可以得到immutable的Point物件.
且我們還增加一個Add函數, 代表兩個Point的X與Y各自相加後產生新的Point物件, 維持immutable.

Immutable物件的條件

  1. 所有欄位(field)是private且read-only
  2. 只允許在constructo做物件的初始化
  3. 不提供任何public的property setter
  4. 確保任何在物件上的操作,都會回傳新的物件, 而不是修改原來的物件

上一篇
Combinatorial explosion 的重構
下一篇
Introduce Null Object 的重構
系列文
程式淨化計畫:痛苦是重構的起源!31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言