承接上篇,本文深入探討 C# 進階特性:建構函式鏈結、方法覆寫、抽象類別、介面、運算子多載、例外處理、索引子、屬性、委派/事件、垃圾回收、不安全程式碼等,並與 Java 對照說明,助 Java 開發者快速掌握 C# 精髓。
衍生類建構函式隱式呼叫基類建構函式(由基類至衍生類順序執行)。可用 base 明確指定呼叫哪個基類建構函式:
public class Point
{
public Point() { x = 0; y = 0; }
public Point(int x, int y) { this.x = x; this.y = y; }
}
public class ColorPoint : Point
{
public ColorPoint(int x, int y) : base(x, y) // 指定呼叫基類雙參數建構函式
{ color = Color.Red; }
}
Java 對應使用 super 關鍵字。
關鍵差異:Java 方法預設為虛擬;C# 需顯式標記 virtual 才可覆寫,衍生類用 override:
public class CountClass
{
public int count;
public CountClass(int start) { count = start; }
public virtual int StepUp() { return ++count; }
}
class Count100Class : CountClass
{
public Count100Class(int x) : base(x) { }
public override int StepUp() { return count + 100; }
}
覆寫成員必須相同存取修飾詞。非虛擬/靜態方法不可覆寫。
含 abstract 成員的類別必須標記 abstract,不可實例化。衍生類必須實作所有抽象成員(除非衍生類也為抽象):
public abstract class Employee
{
public abstract void Show();
}
public class Manager : Employee
{
private string name;
public Manager(string name) { this.name = name; }
public override void Show() { Console.WriteLine("Name: " + name); }
}
// 使用
Employee emp = new Manager("John Chapman");
emp.Show(); // 多型呼叫 Manager.Show()
介面僅含成員簽章(方法、屬性、事件、索引子),所有成員隱含 public,不可含欄位、建構函式、靜態成員。類別以冒號實作介面:
public interface IMethodInterface
{
void MethodA();
int MethodB(float p1, bool p2);
int ReadOnlyProperty { get; } // 唯讀屬性
}
public class Implementation : IMethodInterface
{
public void MethodA() { /* ... */ }
public int MethodB(float p1, bool p2) { /* ... */ return 0; }
public int ReadOnlyProperty { get { return count; } }
}
多介面實作:class MyClass : IFace1, IFace2。名稱衝突時用完整限定名稱消除歧義(如 IFace1.MethodA())。
C# 支援運算子多載(Java 不支援),所有多載為 static 方法:
public class Complex
{
private float real, img;
public Complex(float r, float i) { real = r; img = i; }
public static Complex operator +(Complex lhs, Complex rhs)
{
return new Complex(lhs.real + rhs.real, lhs.img + rhs.img);
}
public static Complex operator -(Complex lhs, Complex rhs)
{
return new Complex(lhs.real - rhs.real, lhs.img - rhs.img);
}
public void Print() { Console.WriteLine("{0} + {1}i", real, img); }
}
// 使用
Complex A = new Complex(10.5f, 12.5f);
Complex B = new Complex(8.0f, 4.5f);
Complex C = A + B; // 直觀語法
C.Print(); // 18.5 + 17i
可多載運算子:一元(+ - ! ~ ++ -- true false)、二元(+ - * / % & | ^ << >> == != < > <= >=)。== 與 != 必須成對多載。
架構與 Java 相似:try / catch / finally。關鍵差異:
catch 區塊必須按繼承階層從特定到一般排序,編譯器強制檢查(Java 不強制)。checked exception(Java throws 關鍵字)。System.Exception → System.SystemException(CLR 錯誤)與 System.ApplicationException(應用程式錯誤,建議自訂例外繼承此類)。try { /* 開啟檔案 */ }
catch (FileNotFoundException fe) { /* 先處理特定 */ }
catch (IOException ioe) { /* 再處理一般 IO */ }
catch { /* 最後捕獲所有 */ }
finally { /* 釋放資源 */ }
自訂例外:
public class InvalidDepartmentException : ApplicationException
{
public InvalidDepartmentException(string dept)
: base("Invalid Department: " + dept) { }
}
// 拋出
if (dept != "Sales" && dept != "Marketing")
throw new InvalidDepartmentException(dept);
賦予類別陣列式存取語法:
public class Department
{
private string[] employees = new string[10];
public string this[int index]
{
get { if (index >= 0 && index < 10) return employees[index];
else throw new IndexOutOfRangeException(); }
set { if (index >= 0 && index < 10) employees[index] = value;
else throw new IndexOutOfRangeException(); }
}
}
// 使用
Department sales = new Department("Sales");
sales[0] = "Nikki";
sales[1] = "Becky";
Console.WriteLine(sales[0] + ", " + sales[1]);
為型別/成員附加宣告性中繼資料,供執行期反射讀取:
[Serializable]
public class Employee
{
public int ID;
public string Name;
[NonSerialized] public int Salary; // 不序列化
}
[WebMethod]
public string GetTime() { return DateTime.Now.ToShortTimeString(); } // 標記為 Web Service 方法
委派(delegate)是型別安全的函式指標,支援多點廣播。三步驟:宣告、實例化、呼叫。
delegate long MathOp(int a, int b);
MathOp op = new MathOp(MathClass.Add);
long result = op(10, 20); // 呼叫
op = new MathOp(MathClass.Multiply); // 重新指派
result = op(1639, 1525);
事件是特殊委派欄位,前綴 event 關鍵字,限制外部只能 +=/-= 訂閱/退訂,不能直接呼叫:
public delegate void CustomHandler(object sender, EventArgs e);
public event CustomHandler CustomEvent;
public void InvokeEvent() { CustomEvent(this, EventArgs.Empty); } // 僅類別內部可呼叫
CLR 週期性掃描 Managed Heap,回收無參考物件。類似 JVM,但 C# 提供 IDisposable 模式與 using 陳述式釋放非受控資源。
需直接操作記憶體(指標、Win32 API)時,標記 unsafe 區塊:
unsafe static void PointerDemo()
{
int i = 10;
int* p = &i;
Console.WriteLine("*p = " + *p);
}
unsafe { fixed (char* p = array) { /* 固定陣列位置防止 GC 移動 */ } }
fixed 防止 GC 在不安全區塊執行期間移動物件。編譯需 /unsafe 選項。
C# 融合 C++ 效能、Java 簡潔、VB 易用性,提供運算子多載、索引子、屬性、委派、不安全程式碼等強大特性。Java 開發者掌握本系列核心差異,即可順利轉型 .NET 平台開發。