C#中的IEnumerable、.ElementAt和无符号/有符号索引

本文关键字:符号 索引 无符号 中的 IEnumerable ElementAt | 更新日期: 2023-09-27 18:24:50

这只是一个语言好奇心,而不是问题。

IEnumerable的ElementAt()方法接受整数以获取可枚举集合的第N个元素。

例如

var list = new List<char>() { 'a', 'b', 'c' };
var alias = list.AsEnumerable();
int N = 0;
alias.ElementAt(N); //gets 'a'

当然,为什么ElementAt()不接受无符号整数(uint)呢?例如

uint N = 0;
alias.ElementAt(N); //doesn't compile 

我能理解为什么ElementAt可以接受整数来允许负索引(例如Python允许负索引,其中list[-1]指的是最后一个元素),所以即使C#不使用负索引,也要接受那些使用负索引的语言的负索引。

但我不太明白禁止无符号整数的理由,如果有什么不同的话,无符号整数更好,因为它可以保证索引不会为负(所以只需要检查范围的上限)。

我能想到的最好的事情可能是CLR团队决定对有符号整数进行标准化,以允许其他具有负索引的语言(例如Python)使用相同的代码,并确保不同语言之间的范围一致。

对于.ElementAt()不允许使用无符号整数的原因,有人有更好/权威的解释吗?

-Marcin

C#中的IEnumerable、.ElementAt和无符号/有符号索引

真正的原因是.NET数组可以是基于非零的,即使C#语言不支持声明这样的数组。您仍然可以使用Array.CreateInstance方法(Type,Int32[],Int32]])创建它们。注意所创建对象类型的特殊名称(System.Int32[*]),其中带有星号。

列表是在内部使用数组实现的,使用不同的类型进行索引是不现实的。

此外,Count属性通常参与数组索引计算,其中部分结果可能为负数。在表达式中混合类型会很麻烦并且容易出错。

拥有一个不能表示负索引的类型对错误检测没有帮助。在unchecked操作中使用自动剪裁无论如何都无法修复应用程序中的逻辑数组索引计算错误。

以下示例显示了基于负的数组操作C#:

var negativeBasedArray = Array.CreateInstance(typeof(Int32),
    new []{2}, // array of array sizes for each dimension
    new []{-1}); // array of lower bounds for each dimension
Console.WriteLine(negativeBasedArray.GetType()); // System.Int32[*]
negativeBasedArray.SetValue(123, -1);
negativeBasedArray.SetValue(456, 0);
foreach(var i in negativeBasedArray)
{
    Console.WriteLine(i);
}
// 123
// 456
Console.WriteLine(negativeBasedArray.GetLowerBound(0)); // -1
Console.WriteLine(negativeBasedArray.GetUpperBound(0)); // 0