組件編程並非對傳統面向對象編程(OOP)的拋棄,而是其深化與發展。類作為面向對象的核心靈魂,在 C# 語言中擁有廣泛而深入的應用。許多極具「Sharp」特色的組件特性,實際上都是直接由類封裝而成。因此,深度掌握類的機制,是邁向 C# 專家之路的關鍵一環。
C# 的類是一種封裝數據成員、函數成員及嵌套類型的數據結構。其成員豐富多樣:
除部分外部引入方法外,類及其成員的聲明與實現通常放在一起。關於構造函數、析構函數、域、方法、屬性與索引器的詳細剖析,將在後續章節展開。
C# 通過多種修飾符表達類的不同性質,根據保護級別分為五種:
非嵌套類(命名空間或編譯單元層級)僅能使用 public 和 internal 修飾。new 修飾符僅用於嵌套類,表示隱藏繼承自父類的同名類型。
使用 abstract 修飾的類只能作為父類被繼承,不能實例化。抽象類可包含抽象成員,但非強制。abstract 不能與 new 同時使用。示例:
abstract class A { public abstract void F(); }
abstract class B : A { public void G() {} }
class C : B { public override void F() { /* 實現 F */ } }
類 A 含抽象方法 F(),不可實例化。類 B 繼承 A 但未實現 F(),故仍為抽象類。類 C 實現 F() 後才能實例化。
sealed 修飾符禁止類被繼承。同時使用 abstract 和 sealed 無意義且被禁止。
類是成員的封裝設計,而對象實例化並在其數據成員上操作才是完成任務的根本。實例化語法:MyClass myObject = new MyClass(),new 會調用相應構造函數。C# 所有對象均創建在托管堆上。實例化後的類型稱為對象,核心特徵是擁有自己特有的數據成員拷貝,稱為實例成員。反之,不屬於特定對象的數據成員稱為靜態成員,用 static 聲明。靜態成員只能通過類名引用。
this 引用當前對象實例的成員。在實例方法中可省略 this 直接引用成員,語義相同。靜態成員函數沒有 this 指針。this 主要用於:
// 構造函數中使用 this
class Employee {
public Employee(string name, string alias) {
this.name = name;
this.alias = alias;
}
}
// 作為參數傳遞
CalcTax(this);
// 索引器聲明
public int this[int param] {
get { return array[param]; }
set { array[param] = value; }
}
C# 所有類直接或間接繼承自 System.Object,實現單根繼承。若未指定基類,編譯器預設繼承 Object。Object 類也可用 object 關鍵字表示。掌握其公共接口對理解 C# 類行為至關重要。
面向對象中有兩個重要相等概念:
Object.Equals(objA, objB) 靜態方法先檢查是否均為 null,否則調用 objA.Equals(objB)。實例方法 Equals(obj) 預設實現為引用相等判斷(return this == obj),但為虛方法,建議重寫以判斷值相等。.NET 框架中 String、Int32 等已重寫,但 Array 未重寫。值類型(繼承自 ValueType)均重寫了 Equals 判斷值相等。
注意:x.Equals(null) 返回 false(x 不能為 null)。若兩對象可能為 null,必須用靜態 Object.Equals。對於值類型,重寫 Equals 時應重載 == 運算符;引用類型一般不重載 ==,保持引用相等語義。
靜態方法 ReferenceEquals(objA, objB) 判斷引用相等。引用類型下語義等同於未重載的 ==;值類型下必定返回 false。
為類型提供哈希碼,用於哈希算法/表。重寫 Equals 時必須重寫 GetHashCode,確保值相等的對象哈希碼相等。
GetType():查詢運行時類型,與 typeof 語義相同ToString():返回對象字符串表示,未重寫時返回類型名Finalize():受保護方法,與析構函數相關,後續章節詳述MemberwiseClone():返回「淺拷貝」(按位拷貝,值類型賦值拷貝,引用類型句柄拷貝)。深拷貝需實現 ICloneable 接口using System;
struct A { public int count; }
class B { public int number; }
class C {
public int integer = 0;
public override bool Equals(object obj) {
C c = obj as C;
return c != null && this.integer == c.integer;
}
public override int GetHashCode() { return 2 ^ integer; }
}
class Test {
public static void Main() {
// 結構 A:值類型,預設值相等
A a1, a2; a1.count = 10; a2 = a1;
Console.Write(a1.Equals(a2)); // True
Console.WriteLine(Object.ReferenceEquals(a1, a2)); // False
// 類 B:引用類型,未重寫 Equals,引用相等
B b1 = new B(), b2 = new B(); b1.number = 10; b2.number = 10;
Console.Write(b1 == b2); // False
Console.Write(b1.Equals(b2)); // False
b2 = b1;
Console.Write(b1 == b2); // True
// 類 C:重寫 Equals 和 GetHashCode,值相等
C c1 = new C(), c2 = new C(); c1.integer = 10; c2.integer = 10;
Console.Write(c1 == c2); // False
Console.Write(c1.Equals(c2)); // True
c2 = c1;
Console.Write(c1 == c2); // True
}
}
對類、對象、this 及 System.Object 的深入把握,為掌握 C# 高級特性奠定了堅實基礎。後續將探討成員初始化、內存管理、繼承多態、異常處理等核心主題。