2

在 Delphi 中有 Low() 和 High() 函数返回数组的最低和最高索引维度。这有助于消除迭代数组时容易出错的循环,该循环可能会成为潜在的 +1/-1 数组边界错误的牺牲品,例如在for 循环语句 中的终止条件中使用< =时。

这是 Low/High 函数的示例(在 Delphi 中):

for i := Low(ary) to High(ary) do

现在我在 C# 中使用一个简单的 for 循环语句:

for (int i = 0; i < ary.Length; i++)

我知道有 Array 方法GetDimension(N)但它有其自身的责任,因为我可能会因意外使用错误的维度索引而引入错误。我想我可以用枚举器做一些事情,但我担心与使用for 循环相比,扫描大型数组时会产生显着的性能成本。C# 中是否有等效于高/低的方法?

4

4 回答 4

11

与内在函数low(ary)high(ary)函数等效的 C# 分别是0ary.Length-1。这是因为C# 数组是从零开始的。我看不出为什么Length数组的属性应该具有与 Delphi 不同的性能特征high()

在性能方面,Pascalfor循环与 C 派生语言使用的循环之间的最大区别在于终止测试的评估。考虑一个经典的 Pascalfor循环:

for i := 0 to GetCount()-1 do
  ....

对于 Pascalfor循环,GetCount()仅在循环开始时计算一次。

现在考虑 C 派生语言中的等价物:

for (int i=0; i<GetCount(); i++)
  ....

在此循环中,GetCount()每次循环都会评估。因此,在像 C# 这样的语言中,您需要一个局部变量来避免一遍又一遍地调用该函数。

int N = GetCount();
for (int i=0; i<N; i++)
  ....

在数组的情况下,如果优化器可以确定ary.Length在循环期间没有发生变异,那么编译器可以优化代码。我个人不知道 C# 优化器是否这样做,但请参阅评论以获取更多信息。

在开始重写循环以使用包含数组长度的局部变量之前,请检查它是否有任何区别。几乎可以肯定它不会。我在上面概述的 Pascal 和类 C for 循环之间的区别在语义方面可能比性能更重要。


我特别羡慕的语言是 D。这里可以使用foreach循环,将数组中的每一项呈现为引用,从而允许您修改数组的内容:

void IncArray(int[] array, int increment) {
    foreach (ref e; array) {
        e += increment;
    }
}    
于 2013-03-24T19:01:36.180 回答
4

在 C# 中,下边界始终为零,因此 的等价物Low(ary)0.

对于一维数组,等价于High(ary)is ary.Length - 1。(对于多维数组,无论如何您都需要多个循环。)

于 2013-03-24T19:02:33.700 回答
1

你可以只使用foreach语句吗?喜欢

foreach(int i in ary)
{
. . .
}
于 2013-03-24T19:00:08.667 回答
1

[边界(int Dimension)]

这些边界函数为任何数组的用户指定维度提供起点和终点。第二个维度将用 1 来标注,而不是 0,以此类推。

for (int i = ary.GetLowerBound(0); i <= ary.GetUpperBound(0); i++ )
{}
于 2015-07-14T14:12:06.337 回答