C# 8.0 引入了一种对数组进行切片的便捷方法 - 请参阅官方 C# 8.0 博客文章。
访问数组最后一个元素的语法是
var value = new[] { 10, 11, 12, 13 }; int a = value[^1]; // 13 int b = value[^2]; // 12
我想知道为什么向后访问元素的索引从 1 而不是 0 开始?这有技术原因吗?
为了更好地了解,这里是 Mads Torgersen的评论,解释了 C# 8 博客文章中的这个设计决定:
当涉及到从头到尾的算术时,我们决定遵循0Python指定第一个元素(一如既往),以及^0“长度”元素,即紧随其后的元素结尾。这样你就得到了一个简单的关系,一个元素从开始的位置加上它从结束的位置等于长度。x如果你自己算算^x的话,你会从长度中减去的。 为什么不使用减号 ( -) 而不是新帽子 ( ^) 运算符?这主要与范围有关。再次与 Python 和大多数行业保持一致,我们希望我们的范围在开始时具有包容性,在结束时具有独占性。你传递的索引是什么,说一个范围应该一直到最后?在 C# 中,答案很简单:从头到尾x..^0。x在 Python 中,没有可以给出的明确索引:-0不起作用,因为它等于0,第一个元素!因此,在 Python 中,您必须完全关闭结束索引以表示一个到达末尾的范围:x... 如果计算出范围的结尾,那么您需要记住有特殊的逻辑,以防它出现在0. 如x..-y,其中y被计算出来了0。这是常见的麻烦和错误来源。 最后,请注意,索引和范围是 .NET/C# 中的第一类类型。它们的行为与它们应用的内容无关,甚至与索引器中的使用无关。您可以完全定义自己的索引器,它采用 Index 和另一个采用 Index 的索引器,Range我们将把这样的索引器添加到例如Span。但是,例如,您也可以使用采用范围的方法。
当涉及到从头到尾的算术时,我们决定遵循0Python指定第一个元素(一如既往),以及^0“长度”元素,即紧随其后的元素结尾。这样你就得到了一个简单的关系,一个元素从开始的位置加上它从结束的位置等于长度。x如果你自己算算^x的话,你会从长度中减去的。
0
^0
x
^x
为什么不使用减号 ( -) 而不是新帽子 ( ^) 运算符?这主要与范围有关。再次与 Python 和大多数行业保持一致,我们希望我们的范围在开始时具有包容性,在结束时具有独占性。你传递的索引是什么,说一个范围应该一直到最后?在 C# 中,答案很简单:从头到尾x..^0。x在 Python 中,没有可以给出的明确索引:-0不起作用,因为它等于0,第一个元素!因此,在 Python 中,您必须完全关闭结束索引以表示一个到达末尾的范围:x... 如果计算出范围的结尾,那么您需要记住有特殊的逻辑,以防它出现在0. 如x..-y,其中y被计算出来了0。这是常见的麻烦和错误来源。
-
^
x..^0
-0
x..
x..-y
y
最后,请注意,索引和范围是 .NET/C# 中的第一类类型。它们的行为与它们应用的内容无关,甚至与索引器中的使用无关。您可以完全定义自己的索引器,它采用 Index 和另一个采用 Index 的索引器,Range我们将把这样的索引器添加到例如Span。但是,例如,您也可以使用采用范围的方法。
Range
Span
我认为这是为了匹配我们习惯的经典语法:
value[^1] == value[value.Length - 1]
如果它使用 0,当这两种语法并排使用时会造成混淆。这样,它的认知负荷 较低。
Python 等其他语言也使用相同的约定。