C# 8.0引入了一种对数组进行切片的便捷方法-请参阅official C# 8.0 blogpost。
访问数组的最后一个元素的语法是
var value = new[] { 10, 11, 12, 13 };
int a = value[^1]; // 13
int b = value[^2]; // 12
我想知道为什么向后访问元素的索引从1而不是0开始?这是有技术原因的吗?
发布于 2019-01-08 21:08:00
官方回答
为了获得更好的可见性,这里是Mads Torgersen的评论,解释了C# 8 blog post的这个设计决定
当涉及到从开始和从结束的运算时,我们决定效仿
。
0
指定第一个元素(一如既往),^0
指定“length‘’th”元素,也就是刚结束的那个。这样你就得到了一个简单的关系,其中一个元素从开始的位置加上它从结束的位置等于长度。如果你自己做了这个数学运算,你会从长度中减去^x
中的x
值。
为什么不用减号(-
)代替新的hat (^
)运算符呢?这主要与范围有关。同样,为了与Python和大多数行业保持一致,我们希望我们的范围在开始时是包容的,在结束时是排他的。您传递的表示一个范围应该一直到结尾的索引是什么?在C#中,答案很简单:x..^0
从头到尾都是x
。在Python语言中,没有显式的索引可以提供:-0
不起作用,因为它等于第一个元素0
!因此,在Python语言中,您必须完全关闭end索引,以表示一个到末尾的范围:x..
。如果范围的结束是计算出来的,那么你需要记住有特殊的逻辑,以防它出现在0
中。就像在x..-y
中一样,y
被计算出来并转化为0
。这是一个常见的麻烦和bug的来源。
最后,请注意索引和范围是.NET/C#中的第一类类型。它们的行为与它们应用的内容无关,甚至与索引器中使用的内容无关。你完全可以定义你自己的索引器,这个索引器接受索引,而另一个索引器接受Range
--我们将在Span
中添加这样的索引器。例如,你也可以使用带范围的方法。
我的答案
我认为这是为了与我们习惯的经典语法相匹配:
value[^1] == value[value.Length - 1]
如果它使用0,那么当两种语法并排使用时,它将会令人困惑。这种方式具有较低的认知负荷。
其他语言,如Python,也使用相同的约定。
https://stackoverflow.com/questions/54092458
复制相似问题