
Subscript Syntax #
1. Core Concepts #
- Concept Explanation:
Swift Subscripts allow for quick access to member elements within a
class,struct, orenumusing square brackets[]. This is the mechanism used when accessing an Array viasomeArray[index]or a Dictionary viasomeDictionary[key]. - Key Syntax:
subscript,get,set
2. Example #
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".Logic Explanation:
This code defines a structure named TimesTable to calculate a multiplication table for integers.
- The
subscriptkeyword is used to define the subscript behavior. - The
getkeyword is omitted here, indicating that this is a Read-Only subscript. - When
threeTimesTable[6]is called, Swift executes the logic inside thesubscriptblock and returns the result of3 * 6.
Note A times table is based on fixed mathematical rules, so setting
threeTimesTable[someIndex]to a new value does not make sense. Therefore, theTimesTablesubscript here is defined as read-only.
3. C# #
Concept Mapping: Swift’s subscript corresponds directly to Indexers (this[...]) in C#.
C# Example:
public struct TimesTable
{
private readonly int _multiplier;
public TimesTable(int multiplier)
{
_multiplier = multiplier;
}
// C# Indexer
public int this[int index]
{
get { return _multiplier * index; }
// Read-only, so set is not implemented
}
}
var threeTimesTable = new TimesTable(3);
Console.WriteLine($"six times three is {threeTimesTable[6]}");Key Difference Analysis:
- Syntax Aspect:
- Definition Style: C# uses the
thiskeyword followed by square bracketspublic int this[int index]to define it; Swift uses the dedicated keywordsubscript, and the syntax is more like a function definitionsubscript(index: Int) -> Int.
- Definition Style: C# uses the
Subscript Usage and Dictionary #
1. Core Concepts #
- Concept Explanation:
The specific meaning of a subscript depends on the context. The most common use is as a shortcut for a Collection. You are free to implement subscripts according to business logic. Swift’s
Dictionaryuses subscripts to set and retrieve Key-Value pairs.
2. Example #
var numberOfLegs = ["spider": 8, "ant": 6, "cat": 4]
numberOfLegs["bird"] = 2Logic Explanation: This code demonstrates subscript usage with a Dictionary.
numberOfLegsis a dictionary of type[String: Int].- Via
numberOfLegs["bird"] = 2, we use subscript syntax to add a new key-value pair.
Note The subscript implemented by Swift’s Dictionary type returns an Optional type (e.g.,
Int?). This is because the Key you are querying might not exist in the dictionary. Swift’s Dictionary subscript accepts an Optional when setting, allowing you to express “removing an element” by assigningnil.
3. C# #
Concept Mapping:
This corresponds to the indexer operation of C# Dictionary<TKey, TValue>.
C# Example:
var numberOfLegs = new Dictionary<string, int>
{
{ "spider", 8 },
{ "ant", 6 },
{ "cat", 4 }
};
numberOfLegs["bird"] = 2; // Set or add value, syntax is the same
// But behavior differs when reading:
// int legs = numberOfLegs["dragon"]; // C# will throw KeyNotFoundExceptionKey Difference Analysis:
- Behavioral Aspect:
- Swift:
dictionary[key]returns an Optional (e.g.,Int?). If the Key doesn’t exist, it returnsniland does not crash. This forces developers to handle cases where the value might be missing. - C#:
dictionary[key]throws aKeyNotFoundExceptionimmediately upon reading if the Key does not exist. C# developers usually need to defend usingContainsKeyorTryGetValue.
- Swift:
- Removing Elements: Swift can remove an element via
dict[key] = nil; C# must calldict.Remove(key). Setting the value tonull(if it’s a Reference type) does not remove the Key.
Subscript Options and Multi-Parameters #
1. Core Concepts #
- Concept Explanation: Subscripts can take any number of input parameters, and these parameters can be of any type. Subscripts can also be overloaded, meaning you can define multiple subscripts with different signatures. This is very useful when handling multi-dimensional data structures (like matrices).
- Note:
Subscripts can use Variadic Parameters and default parameter values, but cannot use
in-outparameters.
2. Example #
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.2Logic Explanation:
- The
Matrixstructure stores a 2D matrix flattened into a 1D arraygrid. - It defines a subscript accepting two parameters
subscript(row: Int, column: Int). assertis used in bothgetandsetto ensure indices do not go out of bounds.- Usage involves separating parameters with commas:
matrix[0, 1].
3. C# #
Concept Mapping: C# indexers also support multiple parameters, often used for multi-dimensional arrays or matrix-like structures.
C# Example:
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
{
// Simplified boundary check
return _grid[(row * _columns) + col];
}
set
{
_grid[(row * _columns) + col] = value;
}
}
}
var matrix = new Matrix(2, 2);
matrix[0, 1] = 1.5; // C# syntax is exactly the sameKey Difference Analysis:
- Syntax Aspect: On the call site, Swift’s
matrix[0, 1]is consistent with C#’smatrix[0, 1]syntax. - Parameter Restrictions: Swift explicitly prohibits
in-outparameters in subscripts, which is similar to the restriction where C# indexers cannot usereforoutparameters.
Type Subscripts #
1. Core Concepts #
- Concept Explanation: The examples above are “Instance Subscripts”, meaning you must create an object instance to use them. Swift further supports Type Subscripts, which are subscripts belonging to the “type itself”, called directly on the type name.
- Key Syntax:
static subscript,class subscript(used for class inheritance)
2. Example #
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)Logic Explanation:
- In the
Planetenum, a type subscript is defined usingstatic subscript. - When calling, you don’t need to instantiate
Planet; you use the type name directly:Planet[4]. - Here, it uses
rawValueto initialize and force unwrap (!) to return the corresponding planet.
3. C# #
Concept Mapping: C# currently does not support static indexers.