轉換運算子是替代性型別間操作轉換。替代性即一個類別可取代另一個類別。這可能是好事:衍生類別物件可被基類物件取代,經典例子為形狀繼承。先有形狀類別,衍生出矩形、橢圓、圓形等。任何地方可用圖形取代圓形,這是多態替代性。正確因為圓形是特殊形狀。建立類別時,明確型別轉換可自動完成。.NET 類別繼承中 System.Object 為所有型別基類,故任何型別可用 System.Object 取代。同理,你建立的任何型別應可用其實作介面、基類介面或基類取代。不僅如此,C# 還支援其他轉換。
為某型別添加轉換運算子,等於告訴編譯器:你的型別可被目標型別取代。這可能引發潛在錯誤,因你的型別很可能不能被目標型別取代(譯註:非指繼承關係轉換,而是 C# 允許的另一種轉換)。副作用:修改目標型別狀態後可能對原型別無效。更糟:若轉換產生暫時物件,副作用是直接修改暫時物件,永久丟失在 GC。總之,使用轉換運算子應基於編譯期型別物件,而非執行期型別物件。使用者可能需對型別進行多樣化強制轉換,產生難維護程式碼。
可用轉換運算子將未知型別轉換為你的型別,更清楚表現建立新物件操作(譯註:此轉換要建立新物件)。
假設類別庫結構如圖 3.1。橢圓與圓皆繼承自形狀,雖信橢圓與圓相關,但決定保留此繼承關係(因不想在繼承中用非抽象葉子類別,從橢圓繼承圓有難題)。但意識到每個圓形應是橢圓,某些橢圓也可能是圓形。(圖 3.1)(譯註:作者例子不恰當,且前面假設原因,請讀者理解作者思想,別鑽牛角尖。相信你的 C# 開發中可能遇到類似轉換問題,只是不太可能從圓形轉橢圓。)
導致添加兩轉換運算子。每個圓形是橢圓,添加隱式轉換從圓形轉新橢圓。隱式轉換在類別要求轉換為另一類別時調用。對應顯式轉換為程式設計師在程式碼用強制轉換運算子。
public class Circle : Shape
{
private PointF _center;
private float _radius;
public Circle() : this(PointF.Empty, 0) { }
public Circle(PointF c, float r) { _center = c; _radius = r; }
public override void Draw() { /*...*/ }
static public implicit operator Ellipse(Circle c)
{
return new Ellipse(c._center, c._center, c._radius, c._radius);
}
}
實作隱式轉換,可在任何要求橢圓地方使用圓形,轉換自動完成:
public double ComputeArea(Ellipse e) { /* return area */ }
Circle c = new Circle(new PointF(3.0f, 0), 5.0f);
ComputeArea(c);
表達可替代型別:圓形已可取代橢圓。ComputeArea 可在替代型別上工作。但看下例:
public void Flatten(Ellipse e) { e.R1 /= 2; e.R2 *= 2; }
Circle c = new Circle(new PointF(3.0f, 0), 5.0f);
Flatten(c);