索引器讓物件支援陣列式存取 obj[index]。關鍵字 this 替代屬性名,可帶參數列表。編譯為 get_Item/set_Item 方法。
class MyCollection
{
private object[] _data = new object[100];
public object this[int index]
{
get => _data[index];
set => _data[index] = value;
}
}
// 使用
var c = new MyCollection();
c[0] = "Hello";
Console.WriteLine(c[0]);
ref/out)。this[int x, int y])。static (屬於實例)。virtual/override/sealed/abstract/extern 同方法。base[index] 呼叫基底實作。
class BitArray
{
private readonly int[] _bits;
public int Length { get; }
public BitArray(int length)
{
if (length < 0) throw new ArgumentOutOfRangeException();
_bits = new int[(length - 1 >> 5) + 1];
Length = length;
}
public bool this[int index]
{
get
{
if (index < 0 || index >= Length) throw new IndexOutOfRangeException();
return (_bits[index >> 5] & (1 << index)) != 0;
}
set
{
if (index < 0 || index >= Length) throw new IndexOutOfRangeException();
if (value) _bits[index >> 5] |= 1 << index;
else _bits[index >> 5] &= ~(1 << index);
}
}
}
// 使用:10 位元陣列,偶數位設 true
var bits = new BitArray(10);
for (int i = 0; i < 10; i++) bits[i] = i % 2 == 0;
for (int i = 0; i < 10; i++) Console.Write(bits[i] + " "); // True False True False ...
優勢:以 int[] 儲存 32 個布林值,記憶體效率提升 32 倍,介面仍如 bool[] 般直觀。
| 類別 | 運算子 |
|---|---|
| 一元 | + - ! ~ ++ -- true false |
| 二元 | + - * / % & | ^ << >> == != > < >= <= |
| 轉換 | implicit (隱式)、explicit (顯式) |
規則:必須 public static,參數為傳值,回傳型別視運算子而定。不可 virtual/override/sealed/abstract。父類別多載運算子被繼承但不可覆寫。
struct Complex
{
public double Re, Im;
public Complex(double re, double im) { Re = re; Im = im; }
public static Complex operator +(Complex a, Complex b) => new Complex(a.Re + b.Re, a.Im + b.Im);
public static Complex operator -(Complex a) => new Complex(-a.Re, -a.Im); // 一元負號
public static Complex operator ++(Complex a) => new Complex(a.Re + 1, a.Im + 1); // 前置/後置皆用此簽章
public override string ToString() => $"{Re} + {Im}i";
}
static void Main()
{
var a = new Complex(3,4);
var b = new Complex(5,6);
Console.WriteLine(-a); // -3 + -4i
Console.WriteLine(a + b); // 8 + 10i
Console.WriteLine(a++); // 3 + 4i (後置傳回舊值)
Console.WriteLine(a); // 4 + 5i
Console.WriteLine(++a); // 5 + 6i (前置傳回新值)
}
關鍵點:++/-- 必須回傳 新實例 (不可修改參數),前置/後置語意由編譯器處理 (前置傳回運算後值,後置傳回運算前值)。
==/!=、>/<、>=/<= 必須成對宣告。Digit 與 byte 互轉
struct Digit
{
private readonly byte _value;
public Digit(byte v) { if (v > 9) throw new ArgumentException(); _value = v; }
// 隱式轉換:Digit → byte (無資訊遺失)
public static implicit operator byte(Digit d) => d._value;
// 顯式轉換:byte → Digit (可能丟失資訊/拋出例外)
public static explicit operator Digit(byte b) => new Digit(b);
}
// 使用
Digit d = 5; // 隱式 byte→Digit? 不行,需顯式:Digit d = (Digit)5;
byte b = d; // 隱式 Digit→byte OK
Digit d2 = (Digit)10; // 執行期拋出 ArgumentException
設計原則:資訊不遺失 → implicit;可能遺失/例外 → explicit。同參數型別不可同時宣告兩者。
索引器與運算子多載皆為「方法的語意包裝」,旨在提供 領域自然的操作介面。善用它們能讓 API 更直觀 (如 matrix[i,j]、v1 + v2、(Digit)b),但濫用會導致語意模糊,僅在型別行為符合直覺數學/集合語意時使用。