這篇在講什麼

Extension Method 的價值不在於讓程式跑更快,而是在於把那些重複、零碎、但非常常用的操作收斂成更好讀的 API。

在 Unity 裡這件事尤其常見,因為像 Vector2Vector3ColorTransform 這些型別,經常會有一堆很像的小操作。

它在解什麼問題

例如你想把物件位置的 z 增加 10,直覺可能會寫:

transform.position.z += 10;

但這樣不行,因為 transform.position 回傳的是 Vector3 的值複本,不是可直接原地修改的引用。

最後常會被迫寫成:

transform.position = new Vector3(
    transform.position.x,
    transform.position.y,
    transform.position.z + 10);

這不是不能用,但很吵,也容易在專案裡一再重複。

Extension Method 的基本寫法

定義 extension method 有三個重點:

  1. 放在 static 類別裡
  2. 方法本身也要是 static
  3. 第一個參數前面加上 this

例如:

public static class VectorExtensions
{
    public static Vector3 WithZ(this Vector3 value, float z)
    {
        value.z = z;
        return value;
    }
}

之後就可以這樣用:

transform.position = transform.position.WithZ(transform.position.z + 10);

為什麼這樣比直接 new 更好

好處通常有幾個:

  • 減少重複樣板碼
  • 讓呼叫端更接近語意表達
  • 同類操作可以集中管理

當某個修改動作在很多地方都會出現時,這種封裝的累積效果很明顯。

Unity 裡哪些型別很適合擴充

常見的目標包括:

  • Vector2
  • Vector3
  • Color
  • Quaternion
  • Transform
  • GameObject

例如:

public static Vector3 AddY(this Vector3 value, float delta)
{
    value.y += delta;
    return value;
}

public static Color WithAlpha(this Color value, float alpha)
{
    value.a = alpha;
    return value;
}

用在值型別時要注意什麼

Vector2Vector3Color 這些都是 struct,所以 extension method 拿到的是複本。

這代表:

  • 你修改的是副本
  • 必須把結果回傳出去
  • 呼叫端也要把回傳值接回去

真正有用的是這種寫法:

transform.position = transform.position.WithZ(10f);

而不是:

transform.position.WithZ(10f);

後者就算語法成立,結果也不會留在 transform.position 上。

命名最好直接表達意圖

WithZ(...)AddY(...)WithAlpha(...) 這種命名,通常會比過短的方法名更清楚。

一眼就能知道這個方法是在:

  • 指定某個欄位
  • 還是做增量修改

可讀性通常比省幾個字更重要。

我自己的整理

Extension Method 很適合拿來做「高頻、小型、語意明確」的操作封裝。

它最適合改善的是:

  • API 手感
  • 可讀性
  • 重複樣板碼

它不會神奇地優化效能,但很能優化日常開發體驗。

先記住的重點

  • Extension Method 是可讀性與封裝工具,不是效能工具
  • 第一個參數要用 this 指定被擴充的型別
  • 面對 struct 時,記得要把回傳值接回去
  • Unity 裡的向量、顏色、Transform 都很適合做這類小擴充