介绍
在现代 C# 中,集合表达式({})、范围(range)和扩展运算符(…)提供了一种简洁的方式来处理列表、哈希集和数组等集合。本文探讨了这些新的语法功能,从主构造函数到集合表达式,再到范围和扩展运算符。
让我们从主构造函数开始
主构造函数用于简化类的初始化。现在,您可以直接在类声明中声明构造函数,从而减少样板代码。它的语法如下:
public class Person(string name, int age)
{
public string Name { get; } = name;
public int Age { get; } = age;
}
//Initialization of class Person
List<Person> people = new()
{
new Person("Alice", 30),
new Person("Bob", 25),
new Person("Charlie", 35)
};
例 1.代码具有主构造函数的 Person 类。
集合表达式
以述例 1 中显示的是初始化列表的传统方法。如下向您展示使用集合表达式初始化列表的全新、现代且更简单的方法。
List<Person> people =
[
new Person("Alice", 30),
new Person("Bob", 25),
new Person("Charlie", 35)
];
例 2.使用集合表达式初始化列表。
有常识的开发人员会认为这是个笑话,对吧?“哇,微软将花括号 {…} 改为方括号 […],大惊小怪”。我也是这么想的,直到潘多拉的盒子被打开。看看下面的语法。它显示了其他集合上的集合表达式。这很棒!看看这种一致性。
List<int> list = [1, 2, 3, 4, 5];
HashSet<string> set = ["apple", "banana", "cherry"];
int[] ints = [1, 2, 3, 4, 5];
int[][] jaggedArray =
[
[1, 2, 3],
[4, 5],
[6, 7, 8, 9]
];
范围运算符 […]
范围运算符,如:[2…5] 用于指定数组或字符串中两个索引之间的范围。它提供了一种简洁的方法来对数组和字符串进行切片,而无需显式循环或 Array.Copy 方法。
注意: startIndex 包含在内,endIndex 不包含在内。
- [startIndex … endIndex]: [2…5] 表示从startIndex到endIndex - 1的范围。
- [startIndex …]:这是一个开放式范围,[2…] 表示从 startIndex 到集合末尾的范围。
- [… endIndex]:这甚至是一个开放式范围;[…5] 表示从集合开始到 endIndex - 1 的范围。
- [ … ]:这代表整个集合。
- ^:此运算符允许从集合的末尾进行计数。
下面将介绍每个例子,以便您更好地理解。
我们先从第一个开始,
[startIndex…endIndex] - [2…5]
int[] arr = [1, 2, 3, 4, 5, 6];
int[] result = arr[2..5]; //Output: 3, 4, 5
- 起始索引:起始索引为 2。这对应于索引 2 处的元素,即 3。
- 结束索引:结束索引为 5。这对应于索引 5 处的元素,即 6。
- 范围 [2…5] 转换为从索引 2 到索引 4 的元素(请记住,结束索引是排除的),假设输出将是 3、4、5。
[startIndex …] - [2…]
int[] arr = [1, 2, 3, 4, 5, 6];
int[] result = arr[2..]; //Output: 3, 4, 5, 6
- 起始索引:起始索引为 2。这对应于索引 2 处的元素,即 3。
- 结束索引:没有指定结束索引,因此默认为数组的末尾。
- 范围 [2…] 转换为从索引 2 到数组末尾的元素。因此输出将是 3、4、5、6。
startIndex…] : […5]
int[] arr = [1, 2, 3, 4, 5, 6];
int[] result = arr[..5];//Output: 1, 2, 3, 4, 5
- 起始索引:在…之前未指定起始索引,因此默认为数组的开头,即0。
- 结束索引:结束索引为 5。这对应于索引 5 处的元素,即 6,但由于结束索引是排他性的,因此不包括索引 5 处的元素。
- 范围 […5] 转换为从索引 0 到索引 4 的元素,即 1、2、3、4 和 5。
Range […]
int[] arr = [1, 2, 3, 4, 5, 6];
int[] result = arr[..];//Output: 1, 2, 3, 4, 5, 6
- 起始索引:在…之前未指定起始索引,因此默认为数组的开头,即0。
- 结束索引: … 之后也没有指定结束索引,因此默认为数组的末尾。
- 范围 […] 转换为从索引 0 到数组末尾的元素。所以这是一种复制数组的简单方法。
^1 运算符
int[] arr = [1, 2, 3, 4, 5, 6];
int result = arr[^1];//Output: 6
- ^1 表示“从末尾开始的第一个元素”。
- 这对应于索引 5 处的元素,即 6。
范围 [ … ] 和 ^,如 [ ^3 … ]
int[] arr = [1, 2, 3, 4, 5, 6];
int[] result = arr[^3..];//Output 4, 5, 6
- 起始索引:起始索引 ^3 表示“倒数第三个元素”,对应元素 4。
- 结束索引:没有指定结束索引,因此默认为数组的末尾。
- 范围 [^3…] 转换为从元素 4 到数组末尾的元素。因此输出将是 4、5、6
范围 [ … ] 和 ^, 如 [ … ^3 ]
int[] arr = [1, 2, 3, 4, 5, 6];
int[] result = arr[..^3];//Output: 1, 2, 3
- 起始索引:在“…”之前未指定起始索引,因此默认为数组的开头,即 0。
- 结束索引:同样,^3 表示“从末尾开始的第三个元素”,即 4。由于结束索引是排除的,因此不包括索引 4 处的元素。
- 范围 […^3] 转换为从索引 0 到索引 2 的元素。因此,输出将是 1、2、3。
范围 [ … ] 和 ^,如 [ ^3 … ^1 ]
int[] arr = [1, 2, 3, 4, 5, 6];
int[] result = arr[^3..^1];//Output: 4, 5
- 起始索引:起始索引 ^3 表示“倒数第三个元素”,对应元素 4。
- 结束索引: ^1 表示“从末尾开始的第一个元素”,即 6。由于结束索引是不包含的,因此不包括 6。
- 范围 [3…1] 转换为从元素 4 到元素 5 的元素。因此,输出将是 4, 5
克隆数组
int[] inputArray = [1, 2, 3, 4, 5, 6];
int[] cloneArray1 = [..inputArray]; //Output: 1, 2, 3, 4, 5, 6
int[] cloneArray2 = inputArray[..]; //Output: 1, 2, 3, 4, 5, 6
您可以使用以下任一方法来克隆阵列。
- [… inputArray]:此语法在新的数组初始化器中使用范围运算符。没有任何索引的范围运算符“…”指定整个数组。因此,[…inputArray] 表示“创建一个新数组并用 inputArray 的所有元素填充它”。这实际上将整个输入数组克隆到 cloneArray1 中。
- inputArray[ … ]:此语法 inputArray[…] 使用范围运算符来创建数组的切片。没有任何索引的 […] 表示“从头到尾”,其中包括所有元素。因此,inputArray[…] 会创建一个包含 inputArray 所有元素的新数组。这也会有效地将整个输入数组克隆到 cloneArray2 中。
- cloneArray1 和 cloneArray2 都将包含与 inputArray 相同的元素,从而创建原始数组的克隆。
合并数组
int[] first = [1, 2, 3, 4, 5, 6];
int[] second = [7, 8, 9, 10];
int[] mergedArray = [..first, ..second];//output: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
int[] mergedArray = […first, …second]
- 此行创建了一个新的数组 mergedArray。
- 它使用 …first 将 first 的元素扩展至 mergedArray 中。
- 它使用…second将second的元素扩展至mergedArray中。
- 结果是一个新数组,其中包含第一个数组的所有元素,后跟第二个数组的所有元素。
使用范围运算符进行子字符串提取
string greeting = "Hello, World!";
string helloSubstring = greeting[..5]; // "Hello"
string worldSubstring = greeting[7..12]; // "World"
string worldExclamationSubstring = greeting[7..]; // "World!"
提取子字符串
greeting[…5]
- Greeting[…5] 从字符串开头提取直到索引 5(不包括)的字符。
- 其中包括从索引 0 到 4 的字符,结果为“Hello”。
greeting[7…12]
- Greeting[7…12] 从索引 7 到 11 提取字符。
- 其中包括索引 7 至 11 的字符,结果为“World”。
greeting[7…]
- Greeting[7…] 从索引 7 到字符串末尾提取字符。
- 其中包括从索引 7 到末尾的字符,结果为“World!”。
**当然,这里有一个小提示
当您看到“…”用于指定两个值或索引之间的范围时,它通常被称为“范围运算符”。
当使用“…”来扩展数组或集合的元素时,它通常被称为“扩展运算符”。**
结论
C# 中的这些集合表达式和切片为开发人员开辟了一种初始化集合的一致方法。此代码简洁且易于维护。了解范围运算符对子字符串和数组操作大有帮助。一开始可能会有点令人困惑,但一旦你掌握了它,它就会比以往任何时候都更容易。