
下標語法 (Subscript Syntax) #
1. 核心觀念 #
- 概念解說:
Swift 的 Subscripts (下標) 允許透過中括號
[]快速存取class、struct或enum中的成員元素。這是在存取 Array 時使用someArray[index]或存取 Dictionary 時使用someDictionary[key]的機制。 - 關鍵語法:
subscript,get,set
2. 範例 #
struct TimesTable {
let multiplier: Int
subscript(index: Int) -> Int {
return multiplier * index
}
}
let threeTimesTable = TimesTable(multiplier: 3)
print("six times three is \(threeTimesTable[6])")
// Prints "six times three is 18".邏輯解說:
這段程式碼定義了一個名為 TimesTable 的結構,用來計算數字的乘法表。
- 使用
subscript關鍵字定義了下標行為。 - 這裡省略了
get關鍵字,表示這是一個唯讀 (Read-Only) 的下標。 - 當呼叫
threeTimesTable[6]時,Swift 會執行subscript區塊內的邏輯,回傳3 * 6的結果。
Note 乘法表是基於固定的數學規則,因此將
threeTimesTable[someIndex]設定為新值並不合理,所以此處的TimesTable下標被定義為唯讀。
3. C# #
概念對應: Swift 的 subscript 直接對應到 C# 的 索引子 (Indexers) (this[...])。
C# 範例:
public struct TimesTable
{
private readonly int _multiplier;
public TimesTable(int multiplier)
{
_multiplier = multiplier;
}
// C# Indexer
public int this[int index]
{
get { return _multiplier * index; }
// 唯讀,所以不實作 set
}
}
var threeTimesTable = new TimesTable(3);
Console.WriteLine($"six times three is {threeTimesTable[6]}");關鍵差異分析:
- 語法面:
- 定義方式:C# 使用
this關鍵字加上中括號public int this[int index]來定義;Swift 使用專屬關鍵字subscript,寫法更像函式定義subscript(index: Int) -> Int。
- 定義方式:C# 使用
下標用法與 Dictionary (Subscript Usage) #
1. 核心觀念 #
- 概念解說:
下標的具體意義取決於上下文。最常見的用途是作為集合 (Collection) 的捷徑。你可以根據業務邏輯自由實作下標。Swift 的
Dictionary就是透過下標來設定與讀取鍵值對 (Key-Value pairs)。
2. 範例 #
var numberOfLegs = ["spider": 8, "ant": 6, "cat": 4]
numberOfLegs["bird"] = 2邏輯解說: 這段程式碼展示了字典的下標用法。
numberOfLegs是一個[String: Int]型別的字典。- 透過
numberOfLegs["bird"] = 2,我們使用下標語法新增了一組鍵值對。
Note Swift 的 Dictionary 型別實作的下標,其回傳值是 Optional 型別 (例如
Int?)。這是因為字典中可能不存在你查詢的 Key。Swift 的 Dictionary 下標在 set 時接受的是 Optional,因此能透過指派nil來表達「移除元素」的語意。
3. C# #
概念對應:
這對應到 C# Dictionary<TKey, TValue> 的索引子操作。
C# 範例:
var numberOfLegs = new Dictionary<string, int>
{
{ "spider", 8 },
{ "ant", 6 },
{ "cat", 4 }
};
numberOfLegs["bird"] = 2; // 設定或新增值,語法相同
// 但讀取時行為不同:
// int legs = numberOfLegs["dragon"]; // C# 會拋出 KeyNotFoundException關鍵差異分析:
- 行為面:
- Swift:
dictionary[key]回傳的是 Optional (例如Int?)。如果 Key 不存在,它回傳nil,不會崩潰。這強迫開發者處理值可能為空的情況。 - C#:
dictionary[key]在讀取時,如果 Key 不存在,會直接拋出KeyNotFoundException。C# 開發者通常需要先用ContainsKey或TryGetValue來防禦。
- Swift:
- 刪除元素:Swift 可以透過
dict[key] = nil來刪除元素;C# 必須呼叫dict.Remove(key),將值設為null(若是 Reference type) 並不會移除該 Key。
下標選項與多參數 (Subscript Options) #
1. 核心觀念 #
- 概念解說:
下標可以接受任意數量的參數,參數也可以是任意型別,也允許定義多個不同簽名的下標,稱為
Subscript Overloading。這在處理多維度資料結構(如矩陣)時非常有用。 - Note:
下標可以使用可變參數 (Variadic Parameters) 和預設參數值,但不能使用
in-out參數。
2. 範例 #
struct Matrix {
let rows: Int, columns: Int
var grid: [Double]
init(rows: Int, columns: Int) {
self.rows = rows
self.columns = columns
grid = Array(repeating: 0.0, count: rows * columns)
}
func indexIsValid(row: Int, column: Int) -> Bool {
return row >= 0 && row < rows && column >= 0 && column < columns
}
subscript(row: Int, column: Int) -> Double {
get {
assert(indexIsValid(row: row, column: column), "Index out of range")
return grid[(row * columns) + column]
}
set {
assert(indexIsValid(row: row, column: column), "Index out of range")
grid[(row * columns) + column] = newValue
}
}
}
var matrix = Matrix(rows: 2, columns: 2)
matrix[0, 1] = 1.5
matrix[1, 0] = 3.2邏輯解說:
Matrix結構將二維矩陣扁平化儲存在一維陣列grid中。- 定義了接受兩個參數的下標
subscript(row: Int, column: Int)。 get與set中使用assert來確保索引不越界。- 使用時,參數用逗號分隔:
matrix[0, 1]。
3. C# #
概念對應: C# 的索引子同樣支援多個參數,經常用於處理多維陣列或類似矩陣的結構。
C# 範例:
public struct Matrix
{
private readonly int _rows;
private readonly int _columns;
private double[] _grid;
public Matrix(int rows, int columns)
{
_rows = rows;
_columns = columns;
_grid = new double[rows * columns];
}
public double this[int row, int col]
{
get
{
// 簡化的邊界檢查
return _grid[(row * _columns) + col];
}
set
{
_grid[(row * _columns) + col] = value;
}
}
}
var matrix = new Matrix(2, 2);
matrix[0, 1] = 1.5; // C# 語法完全相同關鍵差異分析:
- 語法面:在呼叫端,Swift 的
matrix[0, 1]與 C# 的matrix[0, 1]寫法一致。 - 參數限制:Swift 明確禁止
in-out參數用於下標,這與 C# 索引子不能使用ref或out參數的限制類似。
型別下標 (Type Subscripts) #
1. 核心觀念 #
- 概念解說: 前面介紹的都是「實體下標 (Instance Subscripts)」,也就是必須先建立物件實體才能使用。Swift 進一步支援 型別下標 (Type Subscripts),這是屬於「型別本身」的下標,直接透過型別名稱呼叫。
- 關鍵語法:
static subscript,class subscript(用於類別繼承)
2. 範例 #
enum Planet: Int {
case mercury = 1, venus, earth, mars, jupiter, saturn, uranus, neptune
static subscript(n: Int) -> Planet {
return Planet(rawValue: n)!
}
}
let mars = Planet[4]
print(mars)邏輯解說:
- 在
Planet列舉中,使用static subscript定義了一個型別下標。 - 呼叫時,不需要實例化
Planet,直接使用型別名稱:Planet[4]。 - 這裡利用
rawValue初始化並強制解包 (!) 來回傳對應的星球。
3. C# #
概念對應: C# 目前不支援靜態索引子(static indexer)。